- Home
- Tutorials
- Flash
- Intermediate
- Object Orientation : Creating an ant swarm
Object Orientation : Creating an ant swarm

Part Two - Realization
Form the root, move Swarm.as to src/as3, and create a Settings class here also. Navigator view should look like this:

Class Ant :
package com.milgra.swarm
{
import flash.geom.Point;
import flash.display.Sprite;
// Sprite extension is needed because we want avatars representing ants
public class Ant extends Sprite
{
// all variable should be public in this class, because subclasses
// use them
public var world : IWorld; // world
public var state : String; // actual state
public var color : uint;
public var health : Number;
public var position : Point;
public function Ant ( xWorld : IWorld )
{
// storing world
world = xWorld;
// initializing position
position = new Point( );
}
// it's an empty function, sublcasses will override it
public function step ( ):void
{
}
// receiving hit from an enemy
public function receiveHit ( hitStrength : Number ):void
{
// substract hit strength from healt
health -= hitStrength;
// if we are dead, removing ourself
if ( health < 0 ) world.removeAnt( this );
// do a little zig-zag when hit
rotation = Math.random( ) * 360;
}
}
}
Class Queen:
package com.milgra.swarm
{
import Settings;
import flash.geom.Point;
public class Queen extends Ant
{
private var food : Number; // food amount
public function Queen ( xPosition:Point , xColor:uint , xWorld : IWorld )
{
// call superclass constructor
super( xWorld );
// set attributes based on Settings class
food = Settings.QUEEN_FOOD;
color = xColor;
health = Settings.QUEEN_HEALTH;
// set position
x = position.x = xPosition.x;
y = position.y = xPosition.y;
// draw avatar
graphics.beginFill( xColor , 1 );
graphics.drawCircle( 0 , 0 , Settings.QUEEN_SIZE );
}
// override Ant's step function
public override function step ( ):void
{
// if we have enough amount of food
if ( food > Settings.ENTITY_FOOD )
{
// adding new drone and worker
world.addDrone( this );
world.addWorker( this );
// substracting food
food -= Settings.ENTITY_FOOD;
}
}
// receive food from worker
public function receiveFood ( xPower:Number ):void
{
food += xPower;
}
}
}
Class MovingAnt:
package com.milgra.swarm
{
public class MovingAnt extends Ant
{
public var turn : Number; // maximal turning in radian
public var angle : Number; // actual angle
public var speed : Number; // speed
public var target : Object; // target to reach
public function MovingAnt ( xWorld : IWorld )
{
// call superclass constructor
super( xWorld );
// set starting angle
angle = 0;
// set maximal turn
turn = Settings.MAX_TURN;
}
protected function search ( ):void
{
// maka move in with random turning angle
angle = angle - turn / 2 + Math.random( ) * turn;
// do movement
move( );
}
// protected function : subclasses see them, external classes don't
protected function reachTarget ( ):void
{
var dx : Number = ( target.position.x - position.x );
var dy : Number = ( target.position.y - position.y );
// calculate direction to target
angle = Math.atan2( dy , dx );
// do movement
move( );
}
// private function : can be accessed only from this class
private function move ( ):void
{
// calcualte new position
position.x += Math.cos( angle ) * speed;
position.y += Math.sin( angle ) * speed;
var dx:Number = position.x - x;
var dy:Number = position.y - y;
// calculate rotation
rotation = Math.atan2( dy , dx ) * 180 / Math.PI;
// set own position
x = position.x;
y = position.y;
// check borders
if ( position.x < 0 ) position.x = stage.stageWidth + position.x;
else if ( position.x > stage.stageWidth ) position.x = 0;
if ( position.y < 0 ) position.y = stage.stageHeight + position.y;
else if ( position.y > stage.stageHeight ) position.y = 0;
}
}
}
Class Drone:
package com.milgra.swarm
{
import Settings;
import flash.geom.Point;
public class Drone extends MovingAnt
{
public var attack : Number; // attack strength
public function Drone ( xQueen:Queen , xWorld : IWorld )
{
// call superclass constructor
super( xWorld );
// set starting position to queens position
position.x = xQueen.position.x;
position.y = xQueen.position.y;
// starting state is searching state
state = "search";
// our color is our queens color
color = xQueen.color;
// get constants
speed = Settings.DRONE_SPEED;
attack = Settings.DRONE_ATTACK;
health = Settings.DRONE_HEALTH;
// draw avatar
graphics.beginFill( color );
graphics.lineStyle( 1 , 0xff0000 , 1 );
graphics.drawEllipse( - Settings.DRONE_WIDTH / 2 ,
- Settings.DRONE_HEIGHT / 2 ,
Settings.DRONE_WIDTH ,
Settings.DRONE_HEIGHT );
}
// override Ant's step
public override function step ( ):void
{
// check state
switch ( state )
{
case "search" :
// do a search movement ( inherited from MovingAnt )
search( );
// check nearby enemies
var enemy:Ant = world.getVisibleEnemy( this );
// if there is an enemy
if ( enemy != null )
{
// set enemy as target
target = enemy;
// set new state
state = "reach";
}
break;
case "reach" :
// do reach movement ( inherited from MovingAnt )
reachTarget( );
// check distance from target
var distance:Number = Point.distance( position , target.position );
// if we are close enough, change state
if ( distance < Settings.CONTACT_DISTANCE ) state = "fight";
break;
case "fight" :
// do reach movement ( inherited from MovingAnt )
reachTarget( );
// hit target
target.receiveHit( attack );
// if target is dead, set state
if ( target.health < 0 ) state = "search";
break;
}
}
}
}
Class Worker:
package com.milgra.swarm
{
import Settings;
import flash.geom.Point;
public class Worker extends MovingAnt
{
private var queen:Queen; // our queen
private var power:Number; // power of actually transported food
public function Worker ( xQueen:Queen , xWorld : IWorld )
{
// call superclass constructor
super( xWorld );
// our position is our queens position
position.x = xQueen.position.x;
position.y = xQueen.position.y;
// starting state is searching state
state = "search";
// set queen and color
queen = xQueen;
color = xQueen.color;
// set constants
speed = Settings.WORKER_SPEED;
health = Settings.WORKER_HEALTH;
// draw avatar
graphics.beginFill( color );
graphics.drawEllipse( - Settings.WORKER_WIDTH / 2 ,
- Settings.WORKER_HEIGHT / 2 ,
Settings.WORKER_WIDTH ,
Settings.WORKER_HEIGHT );
}
// override ant's step
public override function step ( ):void
{
// check state
switch ( state )
{
case "search" :
// do a search movement ( inherited from MovingAnt )
search( );
// check nearby food
var food:Food = world.getVisibleFood( this );
// if got food
if ( food != null )
{
// set food as target
target = food;
// set new state
state = "reach";
}
break;
case "reach" :
// if someone was faster
if ( target.power == 0 )
{
// set searching state
state = "search";
return;
}
// do reach movement ( inherited from MovingAnt )
reachTarget( );
// check ditance
var distance:Number = Point.distance( position , target.position );
// if we are close enough, get food
if ( distance < Settings.CONTACT_DISTANCE )
{
// get food power
power = target.power;
// cleanup food
target.cleanUp( );
// set new state
state = "transfer";
// queen is our new target
target = queen;
}
break;
case "transfer" :
// do reach movement ( inherited from MovingAnt )
reachTarget( );
// check distance
var distance:Number = Point.distance( position , target.position );
// if we are close enough
if ( distance < Settings.CONTACT_DISTANCE )
{
// give food to queen
queen.receiveFood( power );
// reset food power
power = 0;
// set starting state
state = "search";
}
break;
}
}
}
}
Class Food:
package com.milgra.swarm
{
import Settings;
import flash.geom.Point;
import flash.display.Sprite;
public class Food extends Sprite
{
public var world:Swarm;
public var power:Number;
public var position:Point;
public function Food ( xPosition:Point , xWorld:Swarm )
{
position = new Point( );
world = xWorld;
power = Settings.FOOD_POWER;
x = position.x = xPosition.x;
y = position.y = xPosition.y;
graphics.beginFill( Settings.FOOD_COLOR , 1 );
graphics.drawCircle( 0 , 0 , Settings.FOOD_SIZE );
}
public function cleanUp ( ):void
{
power = 0;
world.removeFood( this );
}
}
}

