Example #1
0
float3
OpenSteer::SteerLibrary::
steerForEvasion (const AbstractVehicle& v, 
				 const AbstractVehicle& menace,
                 const float maxPredictionTime)
{
    // offset from this to menace, that distance, unit vector toward menace
    const float3 offset = float3_subtract(make_float3(menace.position()), make_float3(v.position()));
    const float distance = float3_length(offset);

    const float roughTime = distance / menace.speed();
    const float predictionTime = ((roughTime > maxPredictionTime) ?
                                  maxPredictionTime :
                                  roughTime);

    const float3 target = menace.predictFuturePosition (predictionTime);

    return steerForFlee (v, target);
}
Example #2
0
OpenSteer::Vec3 CombatFighter::Steer()
{
    static bool once = true;
    if (once && Stats().m_type == BOMBER && m_leader) {
        //m_instrument = true;
        once = false;
    }

    // A note about obstacle avoidance.  Avoidance of static obstacles (planets,
    // asteroid fields, etc.) are represented in static_obstacle_avoidance.  The
    // analogous avoidance of dynamic obstacles (ships, etc.) -- that is, an
    // overriding move away from an object that the fighter is about to collide
    // with -- is represented in dynamic_obstacle_avoidance.  Another object
    // avoidance factor exists, nonfighter_obstacle_evasion_vec, but it works a
    // bit differently from the other two.  It provides a distance-variable
    // force moving the fighter away, but does not get treated as the only
    // movement force if it exists (as static_obstacle_avoidance and
    // dynamic_obstacle_avoidance do).  Instead, it is just one of the many
    // forces moving the fighter, along with steering towards mission objectives
    // and away from PD, etc.

    const float OBSTACLE_AVOIDANCE_TIME = 1.0;

    const OpenSteer::Vec3 static_obstacle_avoidance =
        steerToAvoidObstacles(OBSTACLE_AVOIDANCE_TIME,
                              m_pathing_engine->Obstacles().begin(),
                              m_pathing_engine->Obstacles().end());

    if (static_obstacle_avoidance != OpenSteer::Vec3::zero)
        return static_obstacle_avoidance;

    const float SEPARATION_RADIUS =  5.0f;
    const float SEPARATION_ANGLE  = -0.707f;
    const float SEPARATION_WEIGHT =  6.0f;

    const float ALIGNMENT_RADIUS = 7.5f;
    const float ALIGNMENT_ANGLE  = 0.7f;
    const float ALIGNMENT_WEIGHT = 6.0f;

    const float COHESION_RADIUS =  9.0f;
    const float COHESION_ANGLE  = -0.15f;
    const float COHESION_WEIGHT =  4.0f;

    const float FORMATION_WEIGHT = 8.0f;

    const float BOMBER_INTERCEPTOR_EVASION_RADIUS =
        Stats().m_type == BOMBER ? 25.0f : SEPARATION_RADIUS;
    const float BOMBER_INTERCEPTOR_EVASION_WEIGHT = 8.0f;

    const float NONFIGHTER_OBSTACLE_AVOIDANCE_RADIUS = 10.0;
    const float NONFIGHTER_OBSTACLE_AVOIDANCE_WEIGHT = 10.0;

    const float POINT_DEFENSE_AVOIDANCE_RADIUS = MAX_POINT_DEFENSE_RANGE * 1.5;
    const float POINT_DEFENSE_AVOIDANCE_WEIGHT = 8.0;

    // The leader (a "fake" fighter that the real fighters in a formation
    // follow) takes into account all other ("fake") fighters in proximity.
    // Followers ("real", or "normal" fighters) only consider its fellow
    // formation-mates its neighbors.
    OpenSteer::AVGroup neighbors;
    OpenSteer::AVGroup nonfighters;
    if (m_leader) {
        const float FIGHTER_RADIUS = std::max(SEPARATION_RADIUS,
                                              std::max(ALIGNMENT_RADIUS,
                                                       COHESION_RADIUS));
        const float NONFIGHTER_RADIUS = std::max(NONFIGHTER_OBSTACLE_AVOIDANCE_RADIUS,
                                                 POINT_DEFENSE_AVOIDANCE_RADIUS);
        m_pathing_engine->GetProximityDB().FindInRadius(
            position(), FIGHTER_RADIUS, neighbors, FIGHTER_FLAGS, EmpireFlag(m_empire_id));
        m_pathing_engine->GetProximityDB().FindInRadius(
            position(), NONFIGHTER_RADIUS, nonfighters, NONFIGHTER_FLAGS);
    } else {
        for (CombatFighterFormation::const_iterator it = m_formation->begin();
             it != m_formation->end();
             ++it) {
            CombatFighterPtr fighter = *it;
            if (fighter->m_formation_position != m_formation_position)
                neighbors.push_back(fighter.get());
        }
    }

    // steer towards mission objectives
    OpenSteer::Vec3 mission_vec;
    if (m_leader && m_mission_weight)
        mission_vec = (m_mission_destination - position()).normalize();

    // steer to maintain formation
    OpenSteer::Vec3 formation_vec;
    m_out_of_formation = OpenSteer::Vec3();
    if (!m_leader) {
        m_out_of_formation = GlobalFormationPosition() - position();
        formation_vec = m_out_of_formation.normalize();
    }

    // steer to avoid interceptors (bombers only)
    OpenSteer::Vec3 bomber_interceptor_evasion_vec;
    OpenSteer::AVGroup interceptor_neighbors;
    if (Stats().m_type == BOMBER) {
        m_pathing_engine->GetProximityDB().FindInRadius(
            position(), BOMBER_INTERCEPTOR_EVASION_RADIUS, interceptor_neighbors,
            INTERCEPTOR_FLAG, EnemyOfEmpireFlags(m_empire_id));
        OpenSteer::Vec3 direction;
        for (std::size_t i = 0; i < interceptor_neighbors.size(); ++i) {
            direction += steerForFlee(interceptor_neighbors[i]->position());
        }
        bomber_interceptor_evasion_vec = direction.normalize();
    }

    // See note at top of function for partial explanation of these variables'
    // meanings.
    OpenSteer::Vec3 nonfighter_obstacle_evasion_vec;
    OpenSteer::Vec3 point_defense_evasion_vec;
    OpenSteer::Vec3 dynamic_obstacle_avoidance;
    if (m_leader) {
        for (std::size_t i = 0; i < nonfighters.size(); ++i) {
            // TODO: Add code to handle non-ships as necessary.
            CombatShip* ship = boost::polymorphic_downcast<CombatShip*>(nonfighters[i]);
            // handle PD avoidance
            OpenSteer::Vec3 away_vec = position() - ship->position();
            float away_vec_length = away_vec.length();
            away_vec /= away_vec_length;
            point_defense_evasion_vec += away_vec * ship->AntiFighterStrength();
            float collision_avoidance_scale_factor =
                std::max(0.0f, NONFIGHTER_OBSTACLE_AVOIDANCE_RADIUS - away_vec_length) /
                NONFIGHTER_OBSTACLE_AVOIDANCE_RADIUS;
            nonfighter_obstacle_evasion_vec += away_vec * collision_avoidance_scale_factor;
            if (OBSTACLE_AVOIDANCE_TIME * speed() < away_vec_length)
                dynamic_obstacle_avoidance += away_vec;
        }
        nonfighter_obstacle_evasion_vec = nonfighter_obstacle_evasion_vec.normalize();
        point_defense_evasion_vec = point_defense_evasion_vec.normalize();
        dynamic_obstacle_avoidance = dynamic_obstacle_avoidance.normalize();
    }
    if (0.0 < dynamic_obstacle_avoidance.lengthSquared())
        return dynamic_obstacle_avoidance;

    // flocking behaviors
    OpenSteer::AVGroup neighbors_to_use;
    if (m_leader) {
        neighbors_to_use.reserve(neighbors.size());
        for (std::size_t i = 0; i < neighbors.size(); ++i) {
            CombatFighter* fighter = boost::polymorphic_downcast<CombatFighter*>(neighbors[i]);
            // exclude self and formation-mates from list
            if (fighter == this || &fighter->m_formation->Leader() == this)
                continue;
            neighbors_to_use.push_back(neighbors[i]);
        }
    } else {
        std::swap(neighbors, neighbors_to_use);
    }

    const OpenSteer::Vec3 separation_vec = steerForSeparation(SEPARATION_RADIUS,
                                                              SEPARATION_ANGLE,
                                                              neighbors_to_use);
    const OpenSteer::Vec3 alignment_vec  = steerForAlignment(ALIGNMENT_RADIUS,
                                                             ALIGNMENT_ANGLE,
                                                             neighbors_to_use);
    const OpenSteer::Vec3 cohesion_vec  = steerForCohesion(COHESION_RADIUS,
                                                           COHESION_ANGLE,
                                                           neighbors_to_use);

    return
        mission_vec * m_mission_weight +
        formation_vec * FORMATION_WEIGHT +
        bomber_interceptor_evasion_vec * BOMBER_INTERCEPTOR_EVASION_WEIGHT +
        nonfighter_obstacle_evasion_vec * NONFIGHTER_OBSTACLE_AVOIDANCE_WEIGHT +
        point_defense_evasion_vec * POINT_DEFENSE_AVOIDANCE_WEIGHT +
        separation_vec * SEPARATION_WEIGHT +
        alignment_vec * ALIGNMENT_WEIGHT +
        cohesion_vec * COHESION_WEIGHT;
}
Vector3 SteeringVehicle::calcFlee(const Vector3& target)
{
	Vector3 steering = Vec3Utils::setYtoZero(steerForFlee(target));
	return steering;
}