Flocking

By combining three of Flint’s actions that manage interactions between particles, we can cause the particles to approach one another but not get too close and to match velocity with each other. The result is flocking behaviour.

package
{
  import org.flintparticles.twoD.emitters.Emitter2D;
  import org.flintparticles.twoD.renderers.DisplayObjectRenderer;

  import flash.display.Sprite;

  [SWF(width='700', height='500', frameRate='60', backgroundColor='#CCCCCC')]
  
  public class Main extends Sprite
  {
    private var emitter:Emitter2D;
    
    public function Main()
    {
      emitter = new Flock();
      
      var renderer:DisplayObjectRenderer = new DisplayObjectRenderer();
      renderer.addEmitter( emitter );
      addChild( renderer );
      
      emitter.start( );
    }
  }
}
package
{
  import org.flintparticles.common.counters.Blast;
  import org.flintparticles.common.initializers.ImageClass;
  import org.flintparticles.twoD.actions.ApproachNeighbours;
  import org.flintparticles.twoD.actions.BoundingBox;
  import org.flintparticles.twoD.actions.MatchVelocity;
  import org.flintparticles.twoD.actions.MinimumDistance;
  import org.flintparticles.twoD.actions.Move;
  import org.flintparticles.twoD.actions.RotateToDirection;
  import org.flintparticles.twoD.actions.SpeedLimit;
  import org.flintparticles.twoD.emitters.Emitter2D;
  import org.flintparticles.twoD.initializers.Position;
  import org.flintparticles.twoD.initializers.Velocity;
  import org.flintparticles.twoD.zones.DiscZone;
  import org.flintparticles.twoD.zones.RectangleZone;

  import flash.geom.Point;

  public class Flock extends Emitter2D
  {
    public function Flock()
    {
      counter = new Blast( 250 );
      
      addInitializer( new ImageClass( Bird ) );
      addInitializer( new Position( new RectangleZone( 10, 10, 680, 480 ) ) );
      addInitializer( new Velocity( new DiscZone( new Point( 0, 0 ), 150, 100 ) ) );

      addAction( new ApproachNeighbours( 150, 100 ) );
      addAction( new MatchVelocity( 20, 200 ) );
      addAction( new MinimumDistance( 10, 600 ) );
      addAction( new SpeedLimit( 100, true ) );
      addAction( new RotateToDirection() );
      addAction( new BoundingBox( 0, 0, 700, 500 ) );
      addAction( new SpeedLimit( 200 ) );
      addAction( new Move() );
    }
  }
}
import org.flintparticles.common.counters.*;
import org.flintparticles.common.initializers.*;
import org.flintparticles.twoD.actions.*;
import org.flintparticles.twoD.emitters.Emitter2D;
import org.flintparticles.twoD.initializers.*;
import org.flintparticles.twoD.renderers.*;
import org.flintparticles.twoD.zones.*;  

var emitter:Emitter2D = new Emitter2D();
emitter.counter = new Blast( 250 );

emitter.addInitializer( new ImageClass( Bird ) );
emitter.addInitializer( new Position( new RectangleZone( 10, 10, 680, 480 ) ) );
emitter.addInitializer( new Velocity( new DiscZone( new Point( 0, 0 ), 150, 100 ) ) );

emitter.addAction( new ApproachNeighbours( 150, 100 ) );
emitter.addAction( new MatchVelocity( 20, 200 ) );
emitter.addAction( new MinimumDistance( 10, 600 ) );
emitter.addAction( new SpeedLimit( 100, true ) );
emitter.addAction( new RotateToDirection() );
emitter.addAction( new BoundingBox( 0, 0, 700, 500 ) );
emitter.addAction( new SpeedLimit( 200 ) );
emitter.addAction( new Move() );

var renderer:DisplayObjectRenderer = new DisplayObjectRenderer();
renderer.addEmitter( emitter );
addChild( renderer );

emitter.start( );
<?xml version="1.0" encoding="utf-8"?>
<s:Application
  xmlns:fx="http://ns.adobe.com/mxml/2009" 
  xmlns:s="library://ns.adobe.com/flex/spark" 
  xmlns:f="http://flintparticles.org/2009/flint2d"
  width="700" height="500"
  backgroundColor="#CCCCCC">
  
<f:DisplayObjectRenderer id="renderer" width="700" height="500">
  <f:emitters>
    <f:Emitter id="emitter" autoStart="true">
      <f:counter>
        <f:Blast startCount="250"/>
      </f:counter>
      <f:initializers>
        <f:Position>
          <f:RectangleZone top="10" left="10" bottom="490" right="690"/>
        </f:Position>
        <f:Velocity>
          <f:DiscZone centerX="0" centerY="0" innerRadius="100" outerRadius="150"/>
        </f:Velocity>
        <f:ImageClass imageClass="{Bird}"/>
      </f:initializers>
      <f:actions>
        <f:Move/>
        <f:RotateToDirection/>
        <f:ApproachNeighbours acceleration="100" maxDistance="150"/>
        <f:MatchVelocity acceleration="200" maxDistance="20"/>
        <f:MinimumDistance acceleration="600" minimum="10"/>
        <f:SpeedLimit limit="100" isMinimum="true"/>
        <f:SpeedLimit limit="200"/>
        <f:BoundingBox left="0" right="700" top="0" bottom="500"/>
      </f:actions>
    </f:Emitter>
  </f:emitters>
</f:DisplayObjectRenderer>
</s:Application>