Beispiel #1
0
void UnitAiMoonGuard :: run (const WorldInterface& world)
{
    assert(world.isAlive(getShipId()));

    scan(world);

    Vector3 v = getShip().getVelocity();
    if (nearestEnemyShip != PhysicsObjectId::ID_NOTHING)
    {
        v = chargeAtTarget(world, nearestEnemyShip, v);
        shootAtShip(world, nearestEnemyShip);
    }
    else
    {
        Vector3 moon_pos = world.getPosition(moon);
        double moon_radius = world.getRadius(moon);
        v = steeringBehaviour->patrolSphere(world,
                                            moon_pos,
                                            moon_radius,
                                            PLANETOID_AVOID_DISTANCE);
        //printf("Patrolling...\n");
    }
    v = avoidShips(world, v);
    v = avoidRingParticles(world, v);

    getShipAi().setDesiredVelocity(v);
}
void UnitAiMoonGuard::patrolMoon(const WorldInterface& world, const PhysicsObjectId& moonID)
{
    Vector3         planetoid_center = world.getPosition(moonID);
    double          planetoid_radius = world.getRadius(moonID);
    Vector3 desired_velocity = m_steering_behaviour.patrolSphere(world, planetoid_center,
                               planetoid_radius + PLANETOID_CLEARANCE,
                               planetoid_radius + Const::SHELL_THICKNESS);
    Vector3 avoid_velocity = avoidPlanets(world, desired_velocity);
    avoid_velocity = avoidParticles(world, avoid_velocity);
    avoid_velocity = avoidShips(world, avoid_velocity);
    getShipAi().setDesiredVelocity(avoid_velocity);
}
Vector3 UnitAiMoonGuard::avoidPlanets(const WorldInterface& world, const Vector3& originalVelocity)
{
    PhysicsObjectId planetoid_id = world.getNearestPlanetoidId(getShip().getPosition());
    Vector3         planetoid_center = world.getPosition(planetoid_id);
    double          planetoid_radius = world.getRadius(planetoid_id);
    return m_steering_behaviour.avoid(world,
                                      originalVelocity,
                                      planetoid_center,
                                      planetoid_radius,
                                      PLANETOID_CLEARANCE,
                                      PLANETOID_AVOID_DISTANCE);
}
Beispiel #4
0
Vector3 UnitAiMoonGuard::avoidPlanetoids(const WorldInterface &world, const Vector3& orig_velocity)
{
    Vector3 planetoid_pos = world.getPosition(nearestPlanetoid);
    double planetoid_radius = world.getRadius(nearestPlanetoid);

    Vector3 v = steeringBehaviour->avoid(world,
                                         orig_velocity,
                                         planetoid_pos,
                                         planetoid_radius,
                                         PLANETOID_CLEARANCE,
                                         PLANETOID_AVOID_DISTANCE);
    //printf("Avoiding Planetoid\n");
    return v;
}
Beispiel #5
0
Vector3 UnitAiMoonGuard::avoidShips(const WorldInterface &world, const Vector3& orig_velocity)
{
    if (nearestShip == PhysicsObjectId::ID_NOTHING ||
            !world.isAlive(nearestShip) ||
            nearestShip == nearestEnemyShip)
    {
        return orig_velocity;
    }

    Vector3 target_pos = world.getPosition(nearestShip);
    double target_radius = world.getRadius(nearestShip);

    Vector3 v = steeringBehaviour->avoid(world,
                                         orig_velocity,
                                         target_pos,
                                         target_radius,
                                         SHIP_CLEARANCE,
                                         SHIP_AVOID_DISTANCE);
    //printf("\tAvoiding Ships\n");
    return v;
}
// avoid only when going to collide
Vector3 SteeringBehaviour :: avoid (const WorldInterface& world,
                                    const Vector3& original_velocity,
                                    const Vector3& sphere_center,
                                    double sphere_radius,
                                    double clearance,
                                    double avoid_distance) const
{
	assert(sphere_radius >= 0.0);
	assert(clearance > 0.0);
	assert(clearance <= avoid_distance);

	if(!world.isAlive(m_id_agent) ||
	   original_velocity.isZero())
	{
		assert(invariant());
		return Vector3::ZERO;
	}

	Vector3 agent_position    = world.getPosition(m_id_agent);
	double  agent_radius      = world.getRadius(m_id_agent);
	double  desired_speed     = world.getShipSpeedMax(m_id_agent);
	Vector3 relative_position = sphere_center - agent_position;
	double  radius_sum        = sphere_radius + agent_radius;

	if(relative_position.isNormGreaterThan(radius_sum + avoid_distance))
	{
		if(DEBUGGING_AVOID)
			cout << "Avoid: Outside avoid distance" << endl;
		assert(invariant());
		return original_velocity.getTruncated(desired_speed);  // too far away to worry about
	}

	Vector3 agent_forward = world.getForward(m_id_agent);

	if(relative_position.dotProduct(agent_forward) < 0.0)
	{
		// past center of object; no cylinder
		if(DEBUGGING_AVOID)
			cout << "Avoid: Departing from object" << endl;

		if(relative_position.isNormLessThan(radius_sum + clearance))
		{
			// we are too close, so flee and slow down

			double distance_fraction = (relative_position.getNorm() - radius_sum) / clearance;
			if(DEBUGGING_AVOID)
				cout << "\tInside panic distance: fraction = " << distance_fraction << endl;
			if(distance_fraction < 0.0)
				distance_fraction = 0.0;

			Vector3 interpolated =  original_velocity.getNormalized() *        distance_fraction +
			                       -relative_position.getNormalized() * (1.0 - distance_fraction);

			if(distance_fraction > AVOID_SPEED_FACTOR_MIN)
				desired_speed *= distance_fraction;
			else
				desired_speed *= AVOID_SPEED_FACTOR_MIN;

			if(original_velocity.isNormLessThan(desired_speed))
				desired_speed = original_velocity.getNorm();

			assert(invariant());
			return interpolated.getCopyWithNorm(desired_speed);
		}
		else
		{
			if(DEBUGGING_AVOID)
				cout << "\tPast object" << endl;
			assert(invariant());
			return original_velocity.getTruncated(desired_speed);  // far enough past object
		}
	}
	else
	{
		// have not reached center of object; check against cylinder
		if(DEBUGGING_AVOID)
			cout << "Avoid: Approaching object" << endl;

		double distance_from_cylinder_center = relative_position.getAntiProjection(agent_forward).getNorm();
		double clearance_fraction            = (distance_from_cylinder_center - radius_sum) / clearance;
		if(DEBUGGING_AVOID)
		{
			cout << "\tTo sphere:         " << relative_position << endl;
			cout << "\tDistance_from_cylinder_center: " << distance_from_cylinder_center << endl;
			cout << "\tRadius_sum:        " << radius_sum << endl;
			cout << "\tClearance:         " << clearance << endl;
			cout << "\tFraction:          " << clearance_fraction << endl;
		}

		if(clearance_fraction < 0.0)
		{
			clearance_fraction = 0.0;
			if(DEBUGGING_AVOID)
				cout << "\tLined up at sphere" << endl;
		}

		if(clearance_fraction > 1.0)
		{
			if(DEBUGGING_AVOID)
				cout << "\tOutside cylinder" << endl;
			assert(invariant());
			return original_velocity;  // outside of danger cylinder
		}
		if(DEBUGGING_AVOID)
			cout << "\tModified fraction: " << clearance_fraction << endl;

		assert(!original_velocity.isZero());
		assert(!agent_forward.isZero());
		Vector3 sideways_vector = -relative_position.getAntiProjection(agent_forward);
		while(sideways_vector.isNormLessThan(AVOID_SIDEWAYS_NORM_MIN))
		{
			// we have almost no sideways, so use a random value
			sideways_vector = Vector3::getRandomUnitVector().getAntiProjection(agent_forward);
			// keep trying until we get a good one
		}
		assert(!original_velocity.isZero());
		assert(!sideways_vector.isZero());
		assert(sideways_vector.isOrthogonal(agent_forward));
		if(DEBUGGING_AVOID)
			cout << "\tSideways: " << sideways_vector << endl;

		Vector3 interpolated = original_velocity.getNormalized() *        clearance_fraction +
		                       sideways_vector  .getNormalized() * (1.0 - clearance_fraction);

		if(original_velocity.isNormLessThan(desired_speed))
			desired_speed = original_velocity.getNorm();

		if(DEBUGGING_AVOID)
			cout << "\tDodging out of cylinder: " << interpolated.getCopyWithNorm(desired_speed) << endl;
		assert(invariant());
		return interpolated.getCopyWithNorm(desired_speed);
	}
}