Sunday, June 11, 2017

c# - Arrive steering behavior


I bought a book called Programming game AI by example and I am trying to implement the arrive steering behavior. The problem I am having is that my objects oscillate around the target position; after oscillating less and less for awhile they finally come to a stop at the target position. Does anyone have any idea why this oscillating behavior occur? Since the examples accompanying the book are written in C++ I had to rewrite the code into C#. Below is the relevant parts of the steering behavior:


private enum Deceleration
{
Fast = 1,

Normal = 2,
Slow = 3
}

public MovingEntity Entity { get; private set; }

public Vector2 SteeringForce { get; private set; }

public Vector2 Target { get; set; }


public Vector2 Calculate()
{
SteeringForce.Zero();

SteeringForce = SumForces();

SteeringForce.Truncate(Entity.MaxForce);

return SteeringForce;
}


private Vector2 SumForces()
{
Vector2 force = new Vector2();

if (Activated(BehaviorTypes.Arrive))
{
force += Arrive(Target, Deceleration.Slow);

if (!AccumulateForce(force))

return SteeringForce;
}

return SteeringForce;
}

private Vector2 Arrive(Vector2 target, Deceleration deceleration)
{
Vector2 toTarget = target - Entity.Position;


double distance = toTarget.Length();

if (distance > 0)
{
//because Deceleration is enumerated as an int, this value is required
//to provide fine tweaking of the deceleration..
double decelerationTweaker = 0.3;

double speed = distance / ((double)deceleration * decelerationTweaker);


speed = Math.Min(speed, Entity.MaxSpeed);

Vector2 desiredVelocity = toTarget * speed / distance;

return desiredVelocity - Entity.Velocity;
}

return new Vector2();
}


private bool AccumulateForce(Vector2 forceToAdd)
{
double magnitudeRemaining = Entity.MaxForce - SteeringForce.Length();

if (magnitudeRemaining <= 0)
return false;

double magnitudeToAdd = forceToAdd.Length();

if (magnitudeToAdd > magnitudeRemaining)

magnitudeToAdd = magnitudeRemaining;

SteeringForce += Vector2.NormalizeRet(forceToAdd) * magnitudeToAdd;

return true;
}

This is the update method of my objects:


public void Update(double deltaTime)
{

Vector2 steeringForce = Steering.Calculate();

Vector2 acceleration = steeringForce / Mass;

Velocity = Velocity + acceleration * deltaTime;

Velocity.Truncate(MaxSpeed);

Position = Position + Velocity * deltaTime;
}


If you want to see the problem with your own eyes you can download a minimal example here.


Thanks in advance.




No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...