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