////////////////////////////////////////////////////////////////////////// // onAttach //virtual void GaRobotComponent::onAttach( ScnEntityWeakRef Parent ) { Super::onAttach( Parent ); StartPosition_ = Parent->getLocalPosition(); TargetPosition_ = Parent->getLocalPosition(); Canvas_ = Parent->getComponentAnyParentByType< ScnCanvasComponent >(); Material_ = Parent->getComponentAnyParent( "DefaultCanvasMaterial_0" ); View_ = ScnCore::pImpl()->findEntity( "CameraEntity_0" )->getComponentByType< ScnViewComponent >(); auto spawnPart = [ & ]( const BcName PartName ) { ScnEntitySpawnParams EntityParams = { "default", PartName, BcName( PartName.getValue(), getParentEntity()->getName().getID() ), MaMat4d(), getParentEntity() }; return ScnCore::pImpl()->spawnEntity( EntityParams ); }; Base_ = spawnPart( "RobotBase" ); Turret_ = spawnPart( "RobotTurret" ); MoveAngle_ = getName().getID() == 0 ? 0.0f : BcPI; }
////////////////////////////////////////////////////////////////////////// // update //virtual void ScnModelComponent::postUpdate( BcF32 Tick ) { Super::postUpdate( Tick ); UpdateFence_.increment(); updateNodes( BaseTransform_ * getParentEntity()->getWorldMatrix() ); #if DEBUG_RENDER_NODES BcU32 NoofNodes = Model_->pHeader_->NoofNodes_; for( BcU32 NodeIdx = 0; NodeIdx < NoofNodes; ++NodeIdx ) { ScnModelNodeTransformData* pNodeTransformData = &pNodeTransformData_[ NodeIdx ]; ScnModelNodePropertyData* pNodePropertyData = &Model_->pNodePropertyData_[ NodeIdx ]; MaMat4d ThisMatrix = pNodeTransformData->WorldTransform_; MaMat4d ParentMatrix = pNodePropertyData->ParentIndex_ != BcErrorCode ? pNodeTransformData_[ pNodePropertyData->ParentIndex_ ].WorldTransform_ : getParentEntity()->getWorldMatrix(); ScnDebugRenderComponent::pImpl()->drawMatrix( ThisMatrix, RsColour::WHITE, 2000 ); ScnDebugRenderComponent::pImpl()->drawLine( ParentMatrix.translation(), ThisMatrix.translation(), RsColour::WHITE, 1000 ); } #endif // DEBUG_RENDER_NODES }
////////////////////////////////////////////////////////////////////////// // GaBallComponent //virtual void GaBallComponent::update( BcReal Tick ) { // Setup rotation. BcQuat Rotation; Rotation.fromEular( Rotation_, 0.0f, 0.0f ); Rotation_ += Tick; //getParentEntity()->setRotation( Rotation ); // Move ball. const BcVec3d& Position = getParentEntity()->getMatrix().translation(); BcVec3d NewPosition = Position + Velocity_ * Tick; if( NewPosition.x() < -18.0f || NewPosition.x() > 18.0f ) { NewPosition -= BcVec3d( Velocity_.x(), 0.0f, 0.0f ) * Tick; Velocity_.x( -Velocity_.x() ); } if( NewPosition.z() < -10.0f || NewPosition.z() > 10.0f ) { NewPosition -= BcVec3d( 0.0f, 0.0f, Velocity_.z() ) * Tick; Velocity_.z( -Velocity_.z() ); } getParentEntity()->setPosition( NewPosition ); }
void RenderComponent::RenderEntity() { // Update render data and send to renderer to queue up m_renderData.setPosX(getParentEntity()->GetPosition().x); m_renderData.setPosY(getParentEntity()->GetPosition().y); m_renderData.setWidth(getParentEntity()->GetWidth()); m_renderData.setHeight(getParentEntity()->GetHeight()); m_renderData.setLayer(getParentEntity()->GetLayer()); Rendering::AddRenderComponentToFrame(&m_renderData); }
////////////////////////////////////////////////////////////////////////// // setupTopology void GaStructureComponent::setupTopology() { // Setup physics. std::vector< GaPhysicsPointMass > PointMasses; std::vector< GaPhysicsConstraint > Constraints; PointMasses.reserve( 4 ); Constraints.reserve( 6 ); // TODO: Calculate this *properly* instead of drunkenly guessing? const BcF32 Size = 64.0f; const BcF32 PointMass = 1.0f; MaVec2d Offsets[3] = { MaVec2d( 0.0f, -1.0f ) * Size * 0.5f, MaVec2d( -0.9f, 0.5f ) * Size * 0.5f, MaVec2d( 0.9f, 0.5f ) * Size * 0.5f, }; /* if( StructureType_ == GaStructureType::BASE ) { Offsets[0] = MaVec2d( 0.0f, -1.0f ) * Size * 0.5f; Offsets[1] = MaVec2d( -0.9f, 1.5f ) * Size * 0.5f; Offsets[2] = MaVec2d( 0.9f, 1.5f ) * Size * 0.5f; } */ MaVec2d Position = getParentEntity()->getWorldPosition().xy(); // Central point + external constraints. PointMasses.emplace_back( GaPhysicsPointMass( Position, 0.05f, 1.0f / PointMass ) ); Constraints.emplace_back( GaPhysicsConstraint( 0, 1, -1.0f, 0.1f ) ); Constraints.emplace_back( GaPhysicsConstraint( 0, 2, -1.0f, 0.1f ) ); Constraints.emplace_back( GaPhysicsConstraint( 0, 3, -1.0f, 0.1f ) ); // Outer edges. for( size_t Idx = 0; Idx < 3; ++Idx ) { const MaVec2d Offset( Offsets[ Idx ] ); PointMasses.emplace_back( GaPhysicsPointMass( Position + Offset, 0.01f, 1.0f / PointMass ) ); Constraints.emplace_back( GaPhysicsConstraint( 1 + Idx, 1 + ( ( Idx + 1 ) % 3 ), -1.0f, 1.0f ) ); } WeightedPoints_.push_back( 1 ); BouyantPoints_.push_back( 2 ); BouyantPoints_.push_back( 3 ); Physics_ = getParentEntity()->getComponentByType< GaPhysicsComponent >(); BcAssert( Physics_ ); Physics_->setup( std::move( PointMasses ), std::move( Constraints ) ); // Grab absolute position. AbsolutePosition_ = getParentEntity()->getWorldPosition().xy(); PSY_LOG( "GaStructureComponent::setupTopology: %f, %f", AbsolutePosition_.x(), AbsolutePosition_.y() ); }
////////////////////////////////////////////////////////////////////////// // setMaterialParameters void ScnLightComponent::setMaterialParameters( BcU32 LightIndex, ScnMaterialComponent* MaterialComponent ) { const MaVec4d& Position( getParentEntity()->getWorldMatrix().row3() ); const MaVec4d& Direction( getParentEntity()->getWorldMatrix().row2() ); MaterialComponent->setLightParameters( LightIndex, MaVec3d( Position.x(), Position.y(), Position.z() ), MaVec3d( Direction.x(), Direction.y(), Direction.z() ), AmbientColour_, DiffuseColour_, AttnC_, AttnL_, AttnQ_ ); }
////////////////////////////////////////////////////////////////////////// // findLongestDirection MaVec3d GaEnemyComponent::findLongestDirection() { // Ray cast in the 4 directions to determine path. BcF32 LongestDistance = 0.0f; MaVec3d LongestDirection( 0.0f, 0.0f, 0.0f ); MaVec3d Directions[] = { MaVec3d( 1.0f, 0.0f, 0.0f ), MaVec3d( -1.0f, 0.0f, 0.0f ), MaVec3d( 0.0f, 1.0f, 0.0f ), MaVec3d( 0.0f, -1.0f, 0.0f ), }; MaVec3d Position = getParentEntity()->getWorldPosition(); BcBSPPointInfo BSPPointInfo; for( BcU32 Idx = 0; Idx < 4; ++Idx ) { if( BSP_->lineIntersection( Position, Position + Directions[ Idx ] * 256.0f, &BSPPointInfo ) ) { if( BSPPointInfo.Distance_ > LongestDistance ) { LongestDistance = BSPPointInfo.Distance_; LongestDirection = Directions[ Idx ]; } } } BcPrintf( "GaEnemyComponent: Got direction [%.1f, %.1f, %.f1]\n", LongestDirection.x(), LongestDirection.y(), LongestDirection.z() ); return LongestDirection; }
//----------------------------------------------------------------------------- // per frame simulation update void Pedestrian::update (const float currentTime, const float elapsedTime) { if( isRemoteObject() ) { // it's up to you - network programmer ;) } else { SLBaseClass::update( currentTime, elapsedTime ); } #if 0 if( false == isRemoteObject() ) { // reverse direction when we reach an endpoint NetPedestrianPlugin* netPedestrianPlugin = dynamic_cast<NetPedestrianPlugin*>(getParentEntity()); if( netPedestrianPlugin->m_bUseDirectedPathFollowing ) { const Color darkRed (0.7f, 0, 0); float const pathRadius = path->radius(); if (osVector3::distance (position(), path->getStartPoint()) < pathRadius ) { pathDirection = +1; annotationXZCircle (pathRadius, path->getStartPoint(), darkRed, 20); } if (osVector3::distance (position(), path->getEndPoint()) < pathRadius ) { pathDirection = -1; annotationXZCircle (pathRadius, path->getEndPoint(), darkRed, 20); } } } #endif }
////////////////////////////////////////////////////////////////////////// // onDetach //virtual void ScnDebugRenderComponent::onDetach( ScnEntityWeakRef Parent ) { getParentEntity()->detach( MaterialComponent_ ); BcAssert( pImpl_ == this ); pImpl_ = NULL; Super::onDetach( Parent ); }
////////////////////////////////////////////////////////////////////////// // onAttach //virtual void ScnDebugRenderComponent::onAttach( ScnEntityWeakRef Parent ) { Super::onAttach( Parent ); getParentEntity()->attach( MaterialComponent_ ); BcAssert( pImpl_ == NULL ); pImpl_ = this; }
////////////////////////////////////////////////////////////////////////// // playSound void GaGameComponent::playSound( std::string Name, BcBool Looping ) { auto SoundEmitter = getParentEntity()->getComponentAnyParentByType< ScnSoundEmitterComponent >(); ScnSoundRef Sound; if( CsCore::pImpl()->requestResource( "sounds", Name, Sound ) ) { SoundEmitter->play( Sound ); } }
////////////////////////////////////////////////////////////////////////// // onAttach void GaStructureComponent::onAttach( ScnEntityWeakRef Parent ) { // Get canvas + font. Canvas_ = Parent->getComponentAnyParentByType< ScnCanvasComponent >(); BcAssert( Canvas_ ); Font_ = Parent->getComponentAnyParentByType< ScnFontComponent >(); BcAssert( Font_ ); Sprite_ = Parent->getComponentAnyParentByType< ScnSpriteComponent >(); BcAssert( Sprite_ ); Physics_ = getParentEntity()->getComponentByType< GaPhysicsComponent >(); BcAssert( Physics_ ); Game_ = getParentEntity()->getComponentAnyParentByType< GaGameComponent >(); BcAssert( Game_ ); // Subscribe to hotspot for pressed. Parent->subscribe( gaEVT_HOTSPOT_PRESSED, this, [ this ]( EvtID, const EvtBaseEvent& InEvent )->eEvtReturn { const auto& Event = InEvent.get< GaHotspotEvent >(); return evtRET_PASS; } ); // Begin build phase event Game_->getParentEntity()->subscribe( gaEVT_GAME_BEGIN_BUILD_PHASE, this, [ this ]( EvtID, const EvtBaseEvent & Event ) { if( StructureType_ == GaStructureType::RESOURCE ) { Game_->spendResources( -CalculatedResourceRate_ ); } return evtRET_PASS; } ); setActive( Active_ ); Level_ = 0; incLevel(); Timer_ = BaseFireRate_; Super::onAttach( Parent ); }
////////////////////////////////////////////////////////////////////////// // playSound void GaRobotComponent::playSound( const std::string& Name ) { ScnSoundRef Sound; if( CsCore::pImpl()->requestResource( "default", Name, Sound ) ) { auto Emitter = getParentEntity()->getComponentByType< ScnSoundEmitterComponent >(); if( Emitter != nullptr ) { Emitter->play( Sound ); } } }
bool DiffuseRenderComponent::AddAttributeAndValue(const ComponentAttribute* attribute) { if(attribute->name == "texture") { if(attribute->valueString != "") { m_renderData.setTexture(Rendering::GetTexture(attribute->valueString.c_str())); m_renderData.setWidth(Rendering::GetTextureWidth(m_renderData.getTexture())); m_renderData.setHeight(Rendering::GetTextureHeight(m_renderData.getTexture())); getParentEntity()->SetWidth(m_renderData.getWidth()); getParentEntity()->SetHeight(m_renderData.getHeight()); } return true; } else { LOG("Something tried to register an invalid attribute to a RenderComponent."); return false; } }
////////////////////////////////////////////////////////////////////////// // setupHotspot void GaStructureComponent::setupHotspot() { auto Sprite = getComponentByType< ScnSpriteComponent >(); if( Sprite ) { BcAssert( ID_ != BcErrorCode ); getParentEntity()->attach< GaHotspotComponent >( BcName::INVALID, ID_, 0, Sprite->getPosition() - Sprite->getSize() * 0.5f, Sprite->getSize() ); } }
////////////////////////////////////////////////////////////////////////// // onPlaying //virtual void ScnSoundEmitterComponent::onPlaying( SsChannel* pSound ) { if( isAttached() ) { // Update parameters. pSound->gain( Gain_ ); //pSound->maxDistance( 1.0f ); //pSound->maxDistance( 1.0f ); pSound->rolloffFactor( 0.05f ); pSound->position( getParentEntity()->getWorldMatrix().translation() ); pSound->pitch( Pitch_ ); } }
////////////////////////////////////////////////////////////////////////// // fireWeaponB void GaRobotComponent::fireWeaponB( BcF32 Radius ) { if( WeaponBTimer_ < 0.0f && Energy_ > WeaponBCost_ ) { auto Robots = getRobots( 1 - Team_ ); if( Robots.size() > 0 ) { Energy_ -= WeaponBCost_; WeaponBTimer_ = WeaponBCoolDown_; MoveTimer_ = WeaponBCoolDown_ * 0.1f; // Spawn entity. ScnEntitySpawnParams EntityParams = { "default", BcName( "WeaponEntity", 1 ), BcName( "WeaponEntity", 1 ), getParentEntity()->getLocalMatrix(), getParentEntity()->getParentEntity() }; auto Entity = ScnCore::pImpl()->spawnEntity( EntityParams ); BcAssert( Entity != nullptr ); auto WeaponComponent = Entity->getComponentByType< GaWeaponComponent >(); WeaponComponent->TargetPosition_ = Robots[ 0 ]->getParentEntity()->getLocalPosition(); // Randomise target position slightly. WeaponComponent->TargetPosition_ += MaVec3d( BcRandom::Global.randRealRange( -1.0f, 1.0f ), 0.0f, BcRandom::Global.randRealRange( -1.0f, 1.0f ) ).normal() * Radius; playSound( "weaponb" ); } } else { playSound( "fail" ); } }
////////////////////////////////////////////////////////////////////////// // getFullName std::string ScnComponent::getFullName() { std::string FullName; ScnEntityWeakRef Parent( getParentEntity() ); if( Parent.isValid() ) { FullName += Parent->getFullName() + "."; } FullName += (*getName()); return FullName; }
////////////////////////////////////////////////////////////////////////// // onAttach //virtual void GaAnimationControllerComponent::onAttach( ScnEntityWeakRef Parent ) { Super::onAttach( Parent ); ScnAnimationComponentRef Animation = getParentEntity()->getComponentByType< ScnAnimationComponent >(); pRootTrack_ = Animation->findNodeByType< ScnAnimationTreeBlendNode >( "Root" ); pIdleTrack_ = Animation->findNodeByType< ScnAnimationTreeTrackNode >( "IdleTrack_0" ); pReloadTrack_ = Animation->findNodeByType< ScnAnimationTreeTrackNode >( "ReloadTrack_0" ); pIdleTrack_->queueAnimation( AnimFire_ ); pReloadTrack_->queueAnimation( AnimReload_ ); BcF32 Speed = 0.9f + ( BcRandom::Global.randReal() + 1.0f * 0.1f ); pIdleTrack_->setSpeed( Speed ); pReloadTrack_->setSpeed( Speed ); }
////////////////////////////////////////////////////////////////////////// // updateParticles void ScnParticleSystemComponent::updateParticles( BcF32 Tick ) { // Wait for upload to have completed. UploadFence_.wait(); // TODO: Iterate over every "affector" at a time, rather than by particle. // - See "updateParticle". MaAABB FullAABB( MaVec3d( 0.0f, 0.0f, 0.0f ), MaVec3d( 0.0f, 0.0f, 0.0f ) ); // Not optimal, but clear code is clear. (For now...) for( BcU32 Idx = 0; Idx < NoofParticles_; ++Idx ) { ScnParticle& Particle = pParticleBuffer_[ Idx ]; if( Particle.Alive_ ) { // Update particle. updateParticle( Particle, Tick ); // Expand AABB by particle's max bounds. const BcF32 MaxHalfSize = BcMax( Particle.Scale_.x(), Particle.Scale_.y() ) * 0.5f; FullAABB.expandBy( Particle.Position_ - MaVec3d( MaxHalfSize, MaxHalfSize, MaxHalfSize ) ); FullAABB.expandBy( Particle.Position_ + MaVec3d( MaxHalfSize, MaxHalfSize, MaxHalfSize ) ); } } // Transform AABB. if( IsLocalSpace_ ) { const MaMat4d& WorldTransform = getParentEntity()->getWorldMatrix(); AABB_ = FullAABB.transform( WorldTransform ); } else { AABB_ = FullAABB; } UpdateFence_.decrement(); }
////////////////////////////////////////////////////////////////////////// // onAttach //virtual void GaIntroComponent::onAttach( ScnEntityWeakRef Parent ) { OsCore::pImpl()->subscribe( osEVT_INPUT_KEYDOWN, this, [ this ]( EvtID ID, const EvtBaseEvent& BaseEvent ) { if( Timer_ > 5.0f ) { ScnCore::pImpl()->spawnEntity( ScnEntitySpawnParams( "SceneEntity", "default", "SceneEntity", MaMat4d(), getParentEntity()->getParentEntity() ) ); ScnCore::pImpl()->removeEntity( getParentEntity() ); return evtRET_REMOVE; } return evtRET_PASS; } ); Canvas_ = getComponentAnyParentByType< ScnCanvasComponent >(); BcAssert( Canvas_ ); Font_ = getComponentAnyParentByType< ScnFontComponent >(); BcAssert( Font_ ); Super::onAttach( Parent ); }
////////////////////////////////////////////////////////////////////////// // getRobots std::vector< class GaRobotComponent* > GaRobotComponent::getRobots( BcU32 Team ) { auto WorldComponent = getParentEntity()->getComponentAnyParentByType< GaWorldComponent >(); return std::move( WorldComponent->getRobots( Team ) ); }
////////////////////////////////////////////////////////////////////////// // update //virtual void GaRobotComponent::update( BcF32 Tick ) { if( Health_ <= 0.0f ) { return; } CurrentOpTimer_ -= Tick; if( CurrentOpTimer_ < 0.0f ) { CurrentOpTimer_ += CurrentOpTime_; // Handle robot program. BcBool ExecutedCode = BcFalse; if( Program_.size() > 0 ) { CurrentOp_ = NextOp_; const auto& Op = Program_[ CurrentOp_ ]; if( Op.State_ == CurrentState_ ) { auto Condition = ProgramFunctionMap_[ Op.Condition_ ]; if( Condition != nullptr ) { if( Condition( this, Op.ConditionVar_ ) ) { auto Operation = ProgramFunctionMap_[ Op.Operation_ ]; if( Operation == nullptr ) { BcPrintf( "No operation \"%s\"\n", Op.Operation_.c_str() ); } else { auto RetVal = Operation( this, Op.OperationVar_ ); if( RetVal != BcErrorCode ) { CurrentState_ = RetVal; } } } } ExecutedCode = BcTrue; } // Advance to next valid op. if( ExecutedCode ) { for( BcU32 Idx = 0; Idx < Program_.size(); ++Idx ) { NextOp_ = ( NextOp_ + 1 ) % Program_.size(); if( Program_[ NextOp_ ].State_ == CurrentState_ ) { break; } } } // Did we fail to run code? If so, reset to op 0 and the state of op 0. if( ExecutedCode == BcFalse ) { NextOp_ = 0; CurrentState_ = Program_[ NextOp_ ].State_; } } } // Grab entity + position. auto Entity = getParentEntity(); auto LocalPosition = Entity->getLocalPosition(); // Move if we need to move towards our target position. if( ( TargetPosition_ - LocalPosition ).magnitudeSquared() > ( TargetDistance_ * TargetDistance_ ) ) { if( MoveTimer_ <= 0.0f ) { Velocity_ += ( TargetPosition_ - LocalPosition ).normal() * MaxVelocity_; } } else { BcF32 SlowDownTick = BcClamp( Tick * 50.0f, 0.0f, 1.0f ); Velocity_ -= ( Velocity_ * SlowDownTick ); } // TODO LATER: Do rotation. if( Velocity_.magnitudeSquared() > 0.1f ) { auto Angle = std::atan2( Velocity_.z(), Velocity_.x() ) + BcPIDIV2; MaMat4d RotMat; RotMat.rotation( MaVec3d( 0.0f, Angle, 0.0f ) ); Base_->setLocalMatrix( RotMat ); } // TODO LATER: Do rotation. auto Robots = getRobots( 1 - Team_ ); if( Robots.size() > 0 ) { auto Robot = Robots[ 0 ]; auto RobotPosition = Robot->getParentEntity()->getLocalPosition(); auto VectorTo = RobotPosition - LocalPosition; // Push out of away. if( VectorTo.magnitude() < 3.0f ) { BcF32 Factor = ( 3.0f - VectorTo.magnitude() ) / 3.0f; BcF32 InvFactor = 1.0f - Factor; Velocity_ = ( -( VectorTo.normal() * MaxVelocity_ ) * Factor * 3.0f ) + ( Velocity_ * InvFactor ); } // Face turret. auto Angle = std::atan2( VectorTo.z(), VectorTo.x() ) + BcPIDIV2; MaMat4d RotMat; RotMat.rotation( MaVec3d( 0.0f, Angle, 0.0f ) ); Turret_->setLocalMatrix( RotMat ); } LocalPosition += Velocity_ * Tick; // Slow down velocity. BcF32 SlowDownTick = BcClamp( Tick * 10.0f, 0.0f, 1.0f ); Velocity_ -= ( Velocity_ * SlowDownTick ); if( Velocity_.magnitude() > MaxVelocity_ ) { Velocity_ = Velocity_.normal() * MaxVelocity_; } // Set local position. Entity->setLocalPosition( LocalPosition ); // Handle health + energy. Health_ = BcClamp( Health_, 0.0f, 100.0f ); Energy_ = BcClamp( Energy_ + ( EnergyChargeRate_ * Tick ), 0.0f, 100.0f ); // Weapon timers. WeaponATimer_ = BcMax( WeaponATimer_ - Tick, -1.0f ); WeaponBTimer_ = BcMax( WeaponBTimer_ - Tick, -1.0f ); MoveTimer_ = BcMax( MoveTimer_ - Tick, -1.0f ); // Health/energy bars. OsClient* Client = OsCore::pImpl()->getClient( 0 ); BcF32 Width = BcF32( Client->getWidth() ) * 0.5f; BcF32 Height = BcF32( Client->getHeight() ) * 0.5f; MaMat4d Projection; Projection.orthoProjection( -Width, Width, Height, -Height, -1.0f, 1.0f ); Canvas_->pushMatrix( Projection ); Canvas_->setMaterialComponent( Material_ ); auto ScreenPos = View_->getScreenPosition( getParentEntity()->getWorldPosition() ); ScreenPos -= MaVec2d( 0.0f, Height / 8.0f ); auto TLPos = ScreenPos - MaVec2d( Width / 16.0f, Height / 64.0f ); auto BRPos = ScreenPos + MaVec2d( Width / 16.0f, Height / 64.0f ); // Draw background. Canvas_->drawBox( TLPos, BRPos, RsColour::BLACK, 0 ); // Draw inner bars. TLPos += MaVec2d( 1.0f, 1.0f ); BRPos -= MaVec2d( 1.0f, 1.0f ); auto HealthTL = MaVec2d( TLPos.x(), TLPos.y() ); auto HealthBR = MaVec2d( TLPos.x() + ( BRPos.x() - TLPos.x() ) * ( Health_ / 100.0f ), ( TLPos.y() + BRPos.y() ) * 0.5f ); auto EnergyTL = MaVec2d( TLPos.x(), ( TLPos.y() + BRPos.y() ) * 0.5f ); auto EnergyBR = MaVec2d( TLPos.x() + ( BRPos.x() - TLPos.x() ) * ( Energy_ / 100.0f ), BRPos.y() ); Canvas_->drawBox( HealthTL, HealthBR, RsColour::GREEN, 0 ); Canvas_->drawBox( EnergyTL, EnergyBR, RsColour::BLUE, 0 ); Canvas_->popMatrix( ); ScnDebugRenderComponent::pImpl()->drawLine( LocalPosition, TargetPosition_, RsColour::WHITE, 0 ); Super::update( Tick ); }
////////////////////////////////////////////////////////////////////////// // stopAllSounds void GaGameComponent::stopAllSounds() { auto SoundEmitter = getParentEntity()->getComponentAnyParentByType< ScnSoundEmitterComponent >(); SoundEmitter->stopAll(); }
//----------------------------------------------------------------------------- // draw this pedestrian into scene void Pedestrian::draw( const float currentTime, const float elapsedTime ) { SLBaseClass::draw( currentTime, elapsedTime ); #if 0 Color kColor; Vec3 kPosition = position(); bool bGotParentColor = false; AbstractPlugin* parentPlugin = dynamic_cast<AbstractPlugin*>(getParentEntity()); ZonePlugin* zonePlugin = NULL; if( NULL != parentPlugin ) { zonePlugin = dynamic_cast<ZonePlugin*>(parentPlugin->getParentPlugin()); bGotParentColor = parentPlugin->queryVehicleColor( *this, kColor ) ; if( true == bGotParentColor ) { } else { if( true == isRemoteObject() ) { kColor = gGreen; Vec3 kTempPosition = kPosition; kTempPosition.y += 0.05f; setPosition( kTempPosition ); } else { kColor = gRed; } kColor.setA( 0.5f ); } } drawBasic2dCircularVehicle (*this, kColor); setPosition( kPosition ); kColor.setA( 1.0f ); EAnnotationMode eMode = getAnnotationMode(); setAnnotationMode( EAnnotationMode_local ); drawTrail( kColor, gWhite ); setAnnotationMode( eMode ); if( NULL != zonePlugin ) { // check for zone memberships // textual annotation std::ostringstream annote; annote << std::setprecision (2) << std::setiosflags (std::ios::fixed); annote << "z["; for( size_t i = 0; i < 4; ++i ) { if( true == getIsZoneMember(i) ) { annote << i; } else { annote << " "; } if( i < 3 ) { annote << "-"; } } annote << "]\n"; //draw borders annote << "b["; for( size_t i = 0; i < 4; ++i ) { if( true == getIsZoneBorderMember(i) ) { annote << i; } else { annote << " "; } if( i < 3 ) { annote << "-"; } } annote << "]"; draw2dTextAt3dLocation (annote, position(), gWhite, drawGetWindowWidth(), drawGetWindowHeight()); } #endif }
//----------------------------------------------------------------------------- // compute combined steering force: move forward, avoid obstacles // or neighbors if needed, otherwise follow the path and wander osVector3 Pedestrian::determineCombinedSteering (const float elapsedTime) { // note: to enable a better view on a remote vehicle we just // skip computing a steering force for these guys // it is the model to use anyways // AI code has nothing todo on the remote side if( isRemoteObject() ) { return osVector3::zero; } // move forward osVector3 steeringForce = forward(); // probability that a lower priority behavior will be given a // chance to "drive" even if a higher priority behavior might // otherwise be triggered. // const float leakThrough = 0.1f; // no random behaviour for network samples const float leakThrough = -1.0f; // determine if obstacle avoidance is required osVector3 obstacleAvoidance; if (leakThrough < frandom01()) { const float oTime = 6; // minTimeToCollision = 6 seconds // ------------------------------------ xxxcwr11-1-04 fixing steerToAvoid // just for testing // obstacleAvoidance = steerToAvoidObstacles (oTime, gObstacles); // obstacleAvoidance = steerToAvoidObstacle (oTime, gObstacle1); // obstacleAvoidance = steerToAvoidObstacle (oTime, gObstacle3); obstacleAvoidance = steerToAvoidObstacles (oTime, gObstacles); // ------------------------------------ xxxcwr11-1-04 fixing steerToAvoid } // if obstacle avoidance is needed, do it if (obstacleAvoidance != osVector3::zero) { steeringForce += obstacleAvoidance; } else { // otherwise consider avoiding collisions with others osVector3 collisionAvoidance; const float caLeadTime = 3; // find all neighbors within maxRadius using proximity database // (radius is largest distance between vehicles traveling head-on // where a collision is possible within caLeadTime seconds.) const float maxRadius = caLeadTime * maxSpeed() * 2; if( _proximityToken != nullptr) { _neighbors.clear(); _proximityToken->findNeighbors (position(), maxRadius, _neighbors); } // allways avoid neighbors // if (leakThrough < frandom01()) { collisionAvoidance = steerToAvoidNeighbors (caLeadTime, _neighbors) * 10; } // if collision avoidance is needed, do it if (collisionAvoidance != osVector3::zero) { steeringForce += collisionAvoidance; } else { #if 0 NetPedestrianPlugin* netPedestrianPlugin = dynamic_cast<NetPedestrianPlugin*>(getParentEntity()); // add in wander component (according to user switch) if (netPedestrianPlugin->m_bWanderSwitch) steeringForce += steerForWander (elapsedTime); #endif // do (interactively) selected type of path following const float pfLeadTime = 3; const bool useDirectPathFollowing(true); const osVector3 pathFollow = (useDirectPathFollowing ? //(netPedestrianPlugin->m_bUseDirectedPathFollowing ? steerToFollowPath (pathDirection, pfLeadTime, *path) : steerToStayOnPath (pfLeadTime, *path)); // add in to steeringForce steeringForce += pathFollow * 0.5; } } #if OPENSTEER_Z_ISUP // return steering constrained to global XY "ground" plane return steeringForce.setZtoZero(); #else // return steering constrained to global XZ "ground" plane return steeringForce.setYtoZero(); #endif }
////////////////////////////////////////////////////////////////////////// // update //virtual void GaEnemyComponent::update( BcF32 Tick ) { // Find move vector. BcF32 MoveSpeed = 2.0f; MaVec3d MoveVector; PulseTimer_ += Tick; // Set direction and handle if we need to change direction. MaVec3d Position = getParentEntity()->getWorldPosition(); MoveVector = Direction_; BcBSPPointInfo BSPPointInfo; if( BSP_->lineIntersection( Position, Position + Direction_ * 256.0f, &BSPPointInfo ) ) { if( BSPPointInfo.Distance_ < 1.0f ) { // New direction. Direction_ = Direction_.reflect( BSPPointInfo.Plane_.normal() ); // Belt & braces: it will become denormalised over time. Direction_.normalise(); // Clamp position (this is to prevent wandering, if angles aren't sitting on an integer, expect weirdness). Position = MaVec3d( BcRound( Position.x() ), BcRound( Position.y() ), BcRound( Position.z() ) ); } } BcF32 PulseTime = 2.0f; if( BSP_->canSeePlayer( Position ) ) { BcPrintf( "I CAN SEE UUU\n" ); PulseTime = 0.5f; IsTargetting_ = BcTrue; TargetTimer_ -= Tick; } else { IsTargetting_ = BcFalse; TargetTimer_ = 3.0f; } // Pulse. if( PulseTimer_ > PulseTime ) { Pressure_->setSample( Position, 0.5f ); PulseTimer_ = 0.0f; } // Shoot player. if( IsTargetting_ && TargetTimer_ < 0.0f ) { BSP_->killPlayer(); } // Set the move. if( !IsTargetting_ ) { MaVec3d AppliedMoveVector = MoveVector; AppliedMoveVector.z( 0.0f ); AppliedMoveVector = AppliedMoveVector.normal() * MoveSpeed; Pawn_->setMove( AppliedMoveVector ); } else { Pawn_->setMove( MaVec3d( 0.0f, 0.0f, 0.0f ) ); } }
////////////////////////////////////////////////////////////////////////// // getWeapons std::vector< class GaWeaponComponent* > GaRobotComponent::getWeapons( MaVec3d Position, BcF32 Radius ) { auto WorldComponent = getParentEntity()->getComponentAnyParentByType< GaWorldComponent >(); return std::move( WorldComponent->getWeapons( Position, Radius ) ); }
void ScnViewComponent::bind( RsFrame* pFrame, RsRenderSort Sort ) { RsContext* pContext = pFrame->getContext(); // Calculate the viewport. BcF32 Width = static_cast< BcF32 >( pContext->getWidth() ); BcF32 Height = static_cast< BcF32 >( pContext->getHeight() ); // If we're using a render target, we want to use it for dimensions. if( RenderTarget_.isValid() ) { Width = static_cast< BcF32 >( RenderTarget_->getWidth() ); Height = static_cast< BcF32 >( RenderTarget_->getHeight() ); } const BcF32 ViewWidth = Width_ * Width; const BcF32 ViewHeight = Height_ * Height; const BcF32 Aspect = ViewWidth / ViewHeight; // Setup the viewport. Viewport_.viewport( static_cast< BcU32 >( X_ * Width ), static_cast< BcU32 >( Y_ * Height ), static_cast< BcU32 >( ViewWidth ), static_cast< BcU32 >( ViewHeight ), Near_, Far_ ); // Create appropriate projection matrix. if( HorizontalFOV_ > 0.0f ) { ViewUniformBlock_.ProjectionTransform_.perspProjectionHorizontal( HorizontalFOV_, Aspect, Near_, Far_ ); } else { ViewUniformBlock_.ProjectionTransform_.perspProjectionVertical( VerticalFOV_, 1.0f / Aspect, Near_, Far_ ); } ViewUniformBlock_.InverseProjectionTransform_ = ViewUniformBlock_.ProjectionTransform_; ViewUniformBlock_.InverseProjectionTransform_.inverse(); // Setup view matrix. ViewUniformBlock_.InverseViewTransform_ = getParentEntity()->getWorldMatrix(); ViewUniformBlock_.ViewTransform_ = ViewUniformBlock_.InverseViewTransform_; ViewUniformBlock_.ViewTransform_.inverse(); // Clip transform. ViewUniformBlock_.ClipTransform_ = ViewUniformBlock_.ViewTransform_ * ViewUniformBlock_.ProjectionTransform_; // Upload uniforms. RsCore::pImpl()->updateBuffer( ViewUniformBuffer_, 0, sizeof( ViewUniformBlock_ ), RsResourceUpdateFlags::ASYNC, [ this ]( RsBuffer* Buffer, const RsBufferLock& Lock ) { BcMemCopy( Lock.Buffer_, &ViewUniformBlock_, sizeof( ViewUniformBlock_ ) ); } ); // Build frustum planes. // TODO: revisit this later as we don't need to do it I don't think. FrustumPlanes_[ 0 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] + ViewUniformBlock_.ClipTransform_[0][0] ), ( ViewUniformBlock_.ClipTransform_[1][3] + ViewUniformBlock_.ClipTransform_[1][0] ), ( ViewUniformBlock_.ClipTransform_[2][3] + ViewUniformBlock_.ClipTransform_[2][0] ), ( ViewUniformBlock_.ClipTransform_[3][3] + ViewUniformBlock_.ClipTransform_[3][0]) ); FrustumPlanes_[ 1 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] - ViewUniformBlock_.ClipTransform_[0][0] ), ( ViewUniformBlock_.ClipTransform_[1][3] - ViewUniformBlock_.ClipTransform_[1][0] ), ( ViewUniformBlock_.ClipTransform_[2][3] - ViewUniformBlock_.ClipTransform_[2][0] ), ( ViewUniformBlock_.ClipTransform_[3][3] - ViewUniformBlock_.ClipTransform_[3][0] ) ); FrustumPlanes_[ 2 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] + ViewUniformBlock_.ClipTransform_[0][1] ), ( ViewUniformBlock_.ClipTransform_[1][3] + ViewUniformBlock_.ClipTransform_[1][1] ), ( ViewUniformBlock_.ClipTransform_[2][3] + ViewUniformBlock_.ClipTransform_[2][1] ), ( ViewUniformBlock_.ClipTransform_[3][3] + ViewUniformBlock_.ClipTransform_[3][1] ) ); FrustumPlanes_[ 3 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] - ViewUniformBlock_.ClipTransform_[0][1] ), ( ViewUniformBlock_.ClipTransform_[1][3] - ViewUniformBlock_.ClipTransform_[1][1] ), ( ViewUniformBlock_.ClipTransform_[2][3] - ViewUniformBlock_.ClipTransform_[2][1] ), ( ViewUniformBlock_.ClipTransform_[3][3] - ViewUniformBlock_.ClipTransform_[3][1] ) ); FrustumPlanes_[ 4 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] - ViewUniformBlock_.ClipTransform_[0][2] ), ( ViewUniformBlock_.ClipTransform_[1][3] - ViewUniformBlock_.ClipTransform_[1][2] ), ( ViewUniformBlock_.ClipTransform_[2][3] - ViewUniformBlock_.ClipTransform_[2][2] ), ( ViewUniformBlock_.ClipTransform_[3][3] - ViewUniformBlock_.ClipTransform_[3][2] ) ); FrustumPlanes_[ 5 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] ), ( ViewUniformBlock_.ClipTransform_[1][3] ), ( ViewUniformBlock_.ClipTransform_[2][3] ), ( ViewUniformBlock_.ClipTransform_[3][3] ) ); // Normalise frustum planes. for ( BcU32 i = 0; i < 6; ++i ) { MaVec3d Normal = FrustumPlanes_[ i ].normal(); BcF32 Scale = 1.0f / -Normal.magnitude(); FrustumPlanes_[ i ] = MaPlane( FrustumPlanes_[ i ].normal().x() * Scale, FrustumPlanes_[ i ].normal().y() * Scale, FrustumPlanes_[ i ].normal().z() * Scale, FrustumPlanes_[ i ].d() * Scale ); } // Setup render node to set the frame buffer, viewport, and clear colour. // TODO: Pass this in with the draw commands down the line. ScnViewComponentViewport* pRenderNode = pFrame->newObject< ScnViewComponentViewport >(); pRenderNode->Sort_ = Sort; pRenderNode->FrameBuffer_ = FrameBuffer_.get(); pRenderNode->Viewport_ = Viewport_; pRenderNode->ClearColour_ = ClearColour_; pRenderNode->EnableClearColour_ = EnableClearColour_; pRenderNode->EnableClearDepth_ = EnableClearDepth_; pRenderNode->EnableClearStencil_ = EnableClearStencil_; pFrame->addRenderNode( pRenderNode ); }
////////////////////////////////////////////////////////////////////////// // onAttach //virtual void ScnModelComponent::onAttach( ScnEntityWeakRef Parent ) { Super::onAttach( Parent ); // Duplicate node data for update/rendering. BcU32 NoofNodes = Model_->pHeader_->NoofNodes_; pNodeTransformData_ = new ScnModelNodeTransformData[ NoofNodes ]; BcMemCopy( pNodeTransformData_, Model_->pNodeTransformData_, sizeof( ScnModelNodeTransformData ) * NoofNodes ); // Create material instances to render with. ScnModelMeshRuntimeList& MeshRuntimes = Model_->MeshRuntimes_; ScnMaterialComponentRef MaterialComponentRef; PerComponentMeshDataList_.reserve( MeshRuntimes.size() ); for( BcU32 Idx = 0; Idx < MeshRuntimes.size(); ++Idx ) { ScnModelMeshData* pMeshData = &Model_->pMeshData_[ Idx ]; ScnModelMeshRuntime* pMeshRuntime = &MeshRuntimes[ Idx ]; TPerComponentMeshData ComponentData; if( pMeshRuntime->MaterialRef_.isValid() ) { BcAssert( pMeshRuntime->MaterialRef_.isValid() && pMeshRuntime->MaterialRef_->isReady() ); ScnShaderPermutationFlags ShaderPermutation = pMeshData->ShaderPermutation_; // Setup lighting. if( isLit() ) { ShaderPermutation |= ScnShaderPermutationFlags::LIGHTING_DIFFUSE; } else { ShaderPermutation |= ScnShaderPermutationFlags::LIGHTING_NONE; } // Even on failure add. List must be of same size for quick lookups. ComponentData.MaterialComponentRef_ = Parent->attach< ScnMaterialComponent >( BcName::INVALID, pMeshRuntime->MaterialRef_, ShaderPermutation ); } // Create uniform buffer for object. if( pMeshData->IsSkinned_ ) { ComponentData.UniformBuffer_ = RsCore::pImpl() ? RsCore::pImpl()->createBuffer( RsBufferDesc( RsBufferType::UNIFORM, RsResourceCreationFlags::STREAM, ScnShaderBoneUniformBlockData::StaticGetClass()->getSize() ) ) : nullptr; } else { ComponentData.UniformBuffer_ = RsCore::pImpl() ? RsCore::pImpl()->createBuffer( RsBufferDesc( RsBufferType::UNIFORM, RsResourceCreationFlags::STREAM, ScnShaderObjectUniformBlockData::StaticGetClass()->getSize() ) ) : nullptr; } // PerComponentMeshDataList_.push_back( ComponentData ); } // Update nodes. UpdateFence_.increment(); updateNodes( BaseTransform_ * getParentEntity()->getWorldMatrix() ); }