bool RelativePositionDetection::execute() { // TODO add angle of objects to panAngle and tiltAngle // TODO use object size in image for distance approximation mPanAngle = DEGREE_TO_RADIAN * getBodyStatus().getPan(); mTiltAngle = DEGREE_TO_RADIAN * getBodyStatus().getTilt(); const RobotConfiguration& botConf = getRobotConfiguration(); const CameraSettings& camSet = getCameraSettings(); mRadiansPerPixelH = DEGREE_TO_RADIAN * botConf.cameraOpeningHorizontal / (double) (camSet.width); mRadiansPerPixelV = DEGREE_TO_RADIAN * botConf.cameraOpeningVertical / (double) (camSet.height); mPrinciplePointX = botConf.principlePointX; mPrinciplePointY = botConf.principlePointY; mCameraHeight = botConf.cameraHeight; mCameraOffsetX = botConf.cameraOffsetX; updateVector(getBall(), &getBallVector()); updateVectors( getGoalPoles().getObjects(), &getGoalPolesVectors().data); updateVectors( getCyanRobots().getObjects(), &getCyanRobotsVectors().data); updateVectors( getMagentaRobots().getObjects(), &getMagentaRobotsVectors().data); updateVectors( getRobots().getObjects(), &getRobotsVectors().data); return true; }
////////////////////////////////////////////////////////////////////////// // 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" ); } }
////////////////////////////////////////////////////////////////////////// // 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 ); }