## Steering Behaviors

With Steering Behaviors we mean a physics model that aims to describe how vehicles (or boids, as the literature calls them when considered in group) try to change their direction of movement.
The "will" to change direction can be AI-driven or physics-driven.

In this model a vehicle can change its movement direction only by steering, as a driver needs to steer the wheel of a car.

Implementing steering behaviors is quite simple. We build them on top of a particle or a rigid body simulation. On a step basis, the state of the particle is updated as usual, finding the next position by integration while behaviors try to change the direction of movement by modifying acceleration. In this sense, behaviors can be seen as force attractors.

Behaviors can be composed and aggregated to form more complex behaviors.

## Steer

Steer is our core function. As said earlier, the vehicle can adjust its orientation by steering.

```public function steer( direction : Vector2 ) : Void
{
var distanceSquared = direction.squaredLength();
if ( distanceSquared > 0 )
{
direction.multiply( maxSpeed / Math.sqrt( distanceSquared ) );
var steer = Vector2.minus( direction, velocity );
steer.limit( maxForce );
}
}
```

As you can see, a vector is provided to the function. This is the desired direction of movement.
This vector is normalized and then scaled to an arbitrary maxSpeed value.
The steer force is calculated by finding the vector from the current velocity to the desired direction and then limited to a maxForce value.
Finally the force is added to the particle acceleration.

Let's see some basic behaviors.

## Seek

Seek is the most basic behavior, the steering direction is given by the vector separating the vehicle position from the target. The vehicle will try to go toward the target point.

```public function seek( target : Vector2 ) : Vector2
{
var direction = Vector2.minus( target, position );
return direction;
}

// during the update process
boid.steer( boid.seek( target ) );
```

Seek it's not very useful alone, because the vehicle will not stop at the target position, but it's very useful when combined with other behaviors.

## Arrive

Arrive is similar to Seek, except the vehicle slows down as it approaches the target.

```public function arrive( target : Vector2 ) : Vector2
{
var separation = seek( target );
var squaredDistance = separation.squaredLength();

if ( squaredDistance > 0 )
{
var distance = Math.sqrt( squaredDistance );
var desiredSpeed = maxSpeed * ( distance / slowingDistance );
var desiredVelocity = Vector2.times( separation, rampedSpeed / distance );
var direction = Vector2.minus( desiredVelocity, velocity );
return direction;
}

return Vector2.zero;
}

// update
boid.steer( boid.arrive( target ) );
```

First the boid checks if it has arrived at the target. Then it calculates the desired velocity. The velocity vector points toward the target and has a magnitude that depends on the distance. If the distance is less than "slowingDistance", the boid accelerates toward the target, otherwise the boid slows down as it gets closer to the target.

## Pursuit

Pursuit is very much like Seek, except the vehicle steers toward a future position, trying to intercept the target instead of just following it. This future position can be calculated with many techniques, for example by adding the current velocity to the current position.

```public function predictPosition( time : Float ) : Vector2
{
var speedSquared = velocity.squaredLength();
if ( speedSquared > 0 )
{
var movementDirection = velocity.copy();
movementDirection.normalize();
var futurePosition = position.copy();
futurePosition.add( Vector2.times( movementDirection, time ) );
return futurePosition;
}
return Vector2.zero;
}

public function pursuit( boid : Boid ) : Vector2
{
return seek( boid.predictPosition( 1.0 ) );
}
```

In the example, a wanderer (see the next behavior) is already in the scene. Try adding some followers.

## Wander

Wander is the act of a vehicle to move around without a specific target. Wander can be implemented in a lot of ways. Following Reynolds' paper, vehicles seek a point on an imaginary circle projected in front of them. At each update, a new point on this circle is calculated. The circle distance and radius affect the wander movement type.

```public function wander() : Vector2
{
var circlePos = velocity.copy();
circlePos.normalize();
circlePos.multiply( wanderDistance );

wanderTheta += MathUtils.random( -wanderDelta, wanderDelta );
var wanderTarget = new Vector2( Math.cos( wanderTheta ) * wanderRadius, Math.sin( wanderTheta ) * wanderRadius );

return seek( wanderTarget );
}
```

## Path Following

With this behavior, a vehicle is forced to follow a path, but it's free to move around it under a certain threshold.
The implementation relies on the type of path of course, but at the core, it's just about calculating a future position and see if the distance from the nearest point on the path is less than an arbitrary value threshold:

```public function follow( path : Path, pathRadius : Float ) : Vector2
{
var futurePosition = predictPosition( 0.5 );
var nearestPoint = path.findNearestPoint( futurePosition );
var separation = Vector2.minus( nearestPoint, futurePosition );

if ( separation.length() > pathRadius )
return seek( nearestPoint );
else
return seek( position );
}
```

## Group Behaviors

A vehicle can live with other vehicles around and behave consequentially. For example, a car might want to avoid other cars and keep a certain distance from them. A bird might want to stay close to other birds to form a flock. These kind of behaviors are called group behaviors because they depend on the state of some (if not all) other vehicles in the system.
In the following example, boids try to form a flock, by responding to 3 simpler behaviors combined together:
- cohesion: boids are attracted to the group center of mass
- separation: boids try not to occupy the same space of other boids
- alignment: boids try to move in the same direction

## Avoid

Obstacle avoidance is the ability of a vehicle to steer before colliding with an obstacle. This behavior is very general and implementation-dependent. In the example below I just projected the movement direction forward and defined a collision radius. This effectively creates a collision rectangle (or a collision cylinder in 3D). If this rectangle collides with an obstacle, the vehicle steers in the shortest direction to avoid it. The length and the width of this rectangle depends on the vehicle agility and prediction factors.
Here I've used a very naive geometric approach to determine collision, but ideally you might want to interface with the collision system to have more accurate results.

## References

Craig Reynolds GDC09