This entry is part of 9 in the series Steering Behaviors

Flocking

Flocking, click to watch

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.

Flocking is created by combining several steering behaviors: Separation, Cohesion and Alignment.

Spearation

Separation

Separation is similar to Unaligned Collision Avoidance. This behavior keeps the vehicles a certain distance away from others. This keeps the vehicles from colliding and crowding to close together.

To calculate separation, check each vehicle against the other vehicles. If the vehicles are too close, repel it using a force based on how close together the vehicles are.

Simply find the too close vehicles and flee them.

Each vehicle adds up all the repelling forces to create the steering force.

Cohesion

Cohesion

Cohesion is the force that keeps the vehicles together. When a vehicle finds itself far away from other vehicles, it moves towards the group. Each vehicle moves towards the others to form a group. Separation keeps them from “merging” into one vehicle.

Each vehicle looks for the near-by vehicles, just like in separation. Then it finds the center of the group (the average of the positions). The vehicle steers towards the center position.

Once the center position is found, you can simply seek that position.

Alignment

Alignment

Alignment makes the vehicles line up and head the same direction. Vehicles align with the vehicles around them.

To calculate alignment, first find all the vehicles nearby. Average the vehicles velocities together to get the average velocity. Apply this force to get all the vehicles to align.

The average velocity is the direction all the surrounding vehicles are traveling. When this is applied to the current vehicle, it aligns itself with the other vehicles.

Flocking

Now that we know the three components of flocking, it’s time to combine them to produce a flock.


public function flock(vehicles:Array):void {
var averageVelocity:Vector2D = velocity.cloneVector(); // used for alignment.
//starting with the current vehicles velocity keeps the vehicles from stopping
var averagePosition:Vector2D = new Vector2D(); //used for cohesion
var counter:int = 0;//used for cohesion
for(var i:int = 0; i < vehicles.length; i++) {//for each vehicle
var vehicle:Vehicle = vehicles[i] as Vehicle;
if(vehicle != this && isInSight(vehicle)) {//if it is not the current vehicle
//and it is in sight
averageVelocity.add(vehicle.velocity); //add its velocity to the average velocity
averagePosition.add(vehicle.position);//add its position to the average position
if(isTooClose(vehicle)) {//if it is too close
flee(vehicle.position);//flee it, this is separation
}
counter++;//increase the counter to use for finding the average
}
}
if(counter > 0) {//if there are vehicles around
averageVelocity.divide(counter);//divide to find average
averagePosition.divide(counter);//divide to find average
seek(averagePosition);//seek the average, this is cohesion
velocity.add(averageVelocity.subtract(velocity).divide(mass).truncate(_maxForce));
//add the average velocity to the velocity after adjusting the force
//this is alignment
}
}

There’s a few references to other functions in there.

First, isInSight. This checks whether the vehicle is close to the current vehicle. If it is, we use it to find averages.


public function isInSight(vehicle:Vehicle):Boolean {
if(position.distance(vehicle.position) > 120) {//this is changed based on the desired flocking style
return false;//you are too far away, do nothing
}
var direction:Vector2D = velocity.cloneVector().normalize();//get the direction
var difference:Vector2D = vehicle.position.cloneVector().subtract(position);//find the difference of the two positions
var dotProd:Number = difference.dotProduct(direction);//dotProduct

if(dotProd < 0) {
return false;//you are too far away and not facing the right direction
}
return true;//you are in sight.
}

The other function is isTooClose.


public function isTooClose(vehicle:Vehicle):Boolean {
return position.distance(vehicle.position) < 80;
}

This returns whether the vehicle is within a certain distance. If it is too close, you flee it, which is separation.
Click here to watch flocking

Series Navigation