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.
deltaTime
from the velocity calculation the object decelerates nice and sharp with my original code. However this change also means my objects reach max speed after just one Update() call which is bad. I thinkdeltaTime
should be there I just found the result interesting. – dbostream Nov 30 '12 at 18:18