Vec2 Boid::Flock(BoidFriend* boids, int count) { Vec2 cohesion, alignment, separation; // average the positions and velocities of all boids in area int sepCount = 0; for (int i = 0; i != count; ++i) { cohesion += boids[i].boid->GetPosition() - GetPosition(); alignment += boids[i].boid->GetVelocity(); if (boids[i].distance < 1.25f) { Vec2 delta = (GetPosition() - boids[i].boid->GetPosition()); if (!delta.IsZero()) { separation += delta.Normalize() / boids[i].distance; ++sepCount; } } } if (count != 0) { cohesion /= count; alignment /= count; } if (sepCount != 0) separation /= sepCount; return Steer(cohesion) + Steer(alignment) + Steer(separation); }
void Boid::AvoidWalls() { for (GameObject* obj = GameObject::All(); obj != NULL; obj = obj->GetNext()) { // do strong separation for walls if (obj->GetType() == GameObject::TWall) { Vec2 delta = GetPosition() - obj->GetPosition(); float dist = delta.Length(); if (dist < 2.f && dist > 0.f) AddForce(Steer(delta.Normalize() / dist)); } } // avoid outer walls Vec2 steer; if (GetPosition().x < 1.f) steer += Steer(Vec2(1.f, 0.f)); if (GetPosition().x > 19.f) steer += Steer(Vec2(-1.f, 0.f)); if (GetPosition().y < 1.f) steer += Steer(Vec2(0.f, 1.f)); if (GetPosition().y > 14.f) steer += Steer(Vec2(0.f, -1.f)); AddForce(2.f * steer); }
// Called every frame void ASkateboardPawn::Tick(float DeltaTime) { Super::Tick(DeltaTime); // Brake the skateboard if grounded and player pressed the brake button if (bBraking && bIsGrounded) { float stopValue = (Mesh->GetPhysicsLinearVelocity().X + Mesh->GetPhysicsLinearVelocity().Y)*0.9f; Mesh->SetAllPhysicsLinearVelocity(Mesh->GetForwardVector()*stopValue); } // The roll of the board has to be corrected in any time CorrectRoll(); // If the board is grounded, we need to also correct the gravity and the pitch if (bIsGrounded) { CorrectGravity(); CorrectPitch(); } if (bAccelerating && AccelerationDelayCount < DeltaTime) { AccelerationDelayCount = AccelerationDelay; // Handling acceleration Accelerate(); } else { AccelerationDelayCount -= DeltaTime; } float rotationAngle = DeltaTime * 15.0f; // rotationSpeed = (CurrentVelocity on X/Z-Plane) * steeringFactor float rotationSpeed = (Mesh->GetPhysicsLinearVelocity().X + Mesh->GetPhysicsLinearVelocity().Y) * 20; if (bSteeringLeft && !bSteeringRight) { Steer(FRotator(0, -rotationAngle, 0)); Mesh->AddForce(Mesh->GetRightVector() * -rotationSpeed); } else if (bSteeringRight && !bSteeringLeft) { Steer(FRotator(0, rotationAngle, 0)); Mesh->AddForce(Mesh->GetRightVector() * rotationSpeed); } }
Vec2 Boid::Attack() { // steer towards nearest player Player* nearest = NULL; Vec2 nearestV; float nearestD = FLT_MAX; for (int i = 0; i != MAX_PLAYERS; ++i) { if (g_Players[i] != NULL) { Vec2 v = g_Players[i]->GetPosition() - GetPosition(); float d = v.Length(); if (d < nearestD) { nearest = g_Players[i]; nearestD = d; nearestV = v; } } } Vec2 player; if (nearest != NULL) return Steer(nearestV); else return Vec2(); }
void Missile::update(const float elapsed_time, bool force) { OpenSteer::Vec3 steer = m_last_steer; if (force || m_pathing_engine->UpdateNumber() % PathingEngine::UPDATE_SETS == serialNumber % PathingEngine::UPDATE_SETS) { const float AT_DESTINATION = speed(); const float AT_DEST_SQUARED = AT_DESTINATION * AT_DESTINATION; float distance_squared = (m_destination - position()).lengthSquared(); CombatObjectPtr target = m_target.lock(); if (distance_squared < AT_DEST_SQUARED) { if (target) { Listener().MissileExploded(shared_from_this()); target->Damage(Stats().m_damage, NON_PD_DAMAGE); } else { Listener().MissileRemoved(shared_from_this()); } delete m_proximity_token; m_proximity_token = 0; m_pathing_engine->RemoveObject(shared_from_this()); return; } else { if (target) m_destination = target->position(); } steer = Steer(); } applySteeringForce(steer, elapsed_time); m_last_steer = steer; m_proximity_token->UpdatePosition(position()); }
Steer SeekerAI::SeekTarget() { if (!self || !target || Overshot()) return Steer(); return Seek(objective); }
Steer StarshipAI::AvoidCollision() { if (!ship || ship->Velocity().length() < 25) return Steer(); return ShipAI::AvoidCollision(); }
Vec2 Boid::Wander() { float r = 1.2f; float d = 1.5f; m_WanderTheta += Rand(-Pi, Pi) * g_FrameTime; float heading = std::atan2f(GetVelocity().y, GetVelocity().y); Vec2 dir = GetVelocity().Normalize() * d; Vec2 offset = Vec2(std::cos(m_WanderTheta + heading), std::sin(m_WanderTheta + heading)) * r; return Steer(offset + dir); }
Steer NavAI::SeekTarget() { if (!ship) return Steer(); if (takeoff) return Seek(objective); if (navpt) { if (quantum_state == 1) { QuantumDrive* q = ship->GetQuantumDrive(); if (q) { if (q->ActiveState() == QuantumDrive::ACTIVE_READY) { q->SetDestination(navpt->Region(), navpt->Location()); q->Engage(); } else if (q->ActiveState() == QuantumDrive::ACTIVE_POSTWARP) { quantum_state = 0; } } } if (distance < 2 * self->Radius()) { ship->SetNavptStatus(navpt, Instruction::COMPLETE); return Steer(); } else { return Seek(objective); } } return Steer(); }
void CombatShip::update(const float elapsed_time, bool force) { OpenSteer::Vec3 steer = m_last_steer; if (force || m_pathing_engine->UpdateNumber() % PathingEngine::UPDATE_SETS == serialNumber % PathingEngine::UPDATE_SETS) { if (m_last_queue_update_turn != m_turn) UpdateMissionQueue(); if (GetShip()->IsArmed()) FireAtHostiles(); steer = Steer(); } applySteeringForce(steer, elapsed_time); m_last_steer = steer; m_proximity_token->UpdatePosition(position()); }
Steer Steer::operator/(double f) const { return Steer(yaw/f, pitch/f, roll/f, brake); }
Steer Steer::operator*(double f) const { return Steer(yaw*f, pitch*f, roll*f, brake); }
Steer Steer::operator-(const Steer& s) const { return Steer(yaw-s.yaw, pitch-s.pitch, roll-s.roll, (brake<s.brake)?brake:s.brake); }
Steer Steer::operator+(const Steer& s) const { return Steer(yaw+s.yaw, pitch+s.pitch, roll+s.roll, (brake>s.brake)?brake:s.brake); }
Steer SeekerAI::AvoidCollision() { return Steer(); }