This entry is part of 9 in the series Steering Behaviors

The next post steering behaviors series is unaligned collision avoidance. We will be using the Vector2D.as and Vehicle.as classes for this. You will need these classes for the this post. This post is based on Craig Reynold’s article Steering Behaviors For Autonomous Characters.

Unaligned Collision Avoidance, click to watch.

Unaligned Collision Avoidance tries to keep vehicles from colliding with each other. Think of a crowded city. There are a lot of people moving around, but no one runs into someone else. If a person detects a approaching collision, he will steer away from the potential collision. The more crowded an area, the closer a person looks. The less crowded an area is, the further away a person searches for a collision. Using the behavior, the look ahead distance can change based on density of vehicles. That is what this steering behavior tries to simulate.

To do this, each vehicle looks at every other vehicle. It uses the velocity to determine if the two will collide. If a collision will happen, it takes action to avoid the collision.

In code, its quite similar to obstacle avoidance, except it uses velocities in the projection.


public function unalignedAvoidance(vehicles:Array):void {
for(var i:int = 0; i < vehicles.length; i++) { //check each vehicle
var forward:Vector2D = velocity.cloneVector().normalize(); //get the forward vector
var diff:Vector2D = vehicles[i].position.cloneVector().add(vehicles[i].velocity.cloneVector().normalize().multiply(checkLength)).subtract(position);

That line is an important one. First it takes the other vehicle’s position. Then it adds its velocity in the length we are checking (this could be time based as well, just multiply velocity by time instead of normalizing it). Finally, it subtracts the current vehicles position to get the difference between the two.

var dotProd:Number = diff.dotProduct(forward);//dot product between forward and difference
if(dotProd > 0) {//they may meet in the future
var ray:Vector2D = forward.cloneVector().multiply(checkLength); //cast a ray in the forward direction
var projection:Vector2D = forward.cloneVector().multiply(dotProd); //project the forward vector
var dist:Number = projection.cloneVector().subtract(diff).length; //get the distance

if(dist < vehicles[i].radius + width && projection.length < ray.length) { //they will meet in the future, we need to fix it
var force:Vector2D = forward.cloneVector().multiply(maxSpeed);//get the maximum change
force.angle += diff.sign(velocity) * Math.PI / 4;//rotate it away from the site of the collision
force.multiply(1 - projection.length / ray.length);//scale it based on the distance between the position and collision site
velocity.add(force);//adjust the velocity
velocity.multiply(projection.length / ray.length);//scale the velocity
}
}
}
}

This will stop most collisions, but it isn’t perfect, especially around the edges of the screen. The vehicles currently don’t look over the edges for potential collisions, so when the wrap around the edge, there may be a collision. This is easily fixable in two ways. Either make it so the vehicles don’t wrap around the edges or vehicles look around the edges.

Click here to see unaligned collision avoidance in action.

Series Navigation