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.threeD.emitters.Emitter3D;
  import org.flintparticles.threeD.renderers.DisplayObjectRenderer;
  import org.flintparticles.threeD.renderers.controllers.FirstPersonCamera;

  import flash.display.Sprite;
  import flash.geom.Vector3D;

  [SWF(width='700', height='500', frameRate='60', backgroundColor='#CCCCCC')]
  public class Main extends Sprite
  {
    private var emitter : Emitter3D;
    private var controller : FirstPersonCamera;

    public function Main()
    {
      emitter = new Flock();

      var renderer : DisplayObjectRenderer = new DisplayObjectRenderer( false );
      renderer.x = 350;
      renderer.y = 250;
      renderer.addEmitter( emitter );
      addChild( renderer );

      renderer.camera.position = new Vector3D( 0, 0, -400 );
      renderer.camera.target = new Vector3D( 0, 0, 0 );
      renderer.camera.projectionDistance = 400;
      controller = new FirstPersonCamera( stage, renderer.camera );
      controller.start();

      emitter.start();
    }
  }
}
package
{
  import org.flintparticles.common.counters.Blast;
  import org.flintparticles.common.initializers.ImageClass;
  import org.flintparticles.threeD.actions.ApproachNeighbours;
  import org.flintparticles.threeD.actions.BoundingBox;
  import org.flintparticles.threeD.actions.MatchVelocity;
  import org.flintparticles.threeD.actions.MinimumDistance;
  import org.flintparticles.threeD.actions.Move;
  import org.flintparticles.threeD.actions.RotateToDirection;
  import org.flintparticles.threeD.actions.SpeedLimit;
  import org.flintparticles.threeD.emitters.Emitter3D;
  import org.flintparticles.threeD.initializers.Position;
  import org.flintparticles.threeD.initializers.Velocity;
  import org.flintparticles.threeD.zones.BoxZone;
  import org.flintparticles.threeD.zones.SphereZone;

  import flash.geom.Vector3D;

  public class Flock extends Emitter3D
  {
    public function Flock()
    {
      counter = new Blast( 300 );
      
      addInitializer( new ImageClass( Bird ) );
      addInitializer( new Position( new BoxZone( 580, 380, 580, new Vector3D( 0, 0, 0 ), new Vector3D( 0, 1, 0 ), new Vector3D( 0, 0, 1 ) ) ) );
      addInitializer( new Velocity( new SphereZone( new Vector3D( 0, 0, 0 ), 150, 100 ) ) );

      addAction( new ApproachNeighbours( 200, 100 ) );
      addAction( new MatchVelocity( 40, 200 ) );
      addAction( new MinimumDistance( 20, 600 ) );
      addAction( new RotateToDirection() );
      addAction( new BoundingBox( -300, 300, -200, 200, -300, 300 ) );
      addAction( new SpeedLimit( 100, true ) );
      addAction( new SpeedLimit( 200 ) );
      addAction( new Move() );
    }
  }
}
import org.flintparticles.common.counters.*;
import org.flintparticles.common.initializers.*;
import org.flintparticles.threeD.actions.*;
import org.flintparticles.threeD.emitters.Emitter3D;
import org.flintparticles.threeD.initializers.*;
import org.flintparticles.threeD.renderers.*;
import org.flintparticles.threeD.renderers.controllers.*;
import org.flintparticles.threeD.zones.*;  

var emitter:Emitter3D = new Emitter3D();
emitter.counter = new Blast( 300 );

emitter.addInitializer( new ImageClass( Bird ) );
emitter.addInitializer( new Position( new BoxZone( 580, 380, 580, new Vector3D( 0, 0, 0 ), new Vector3D( 0, 1, 0 ), new Vector3D( 0, 0, 1 ) ) ) );
emitter.addInitializer( new Velocity( new SphereZone( new Vector3D( 0, 0, 0 ), 150, 100 ) ) );

emitter.addAction( new ApproachNeighbours( 200, 100 ) );
emitter.addAction( new MatchVelocity( 40, 200 ) );
emitter.addAction( new MinimumDistance( 20, 600 ) );
emitter.addAction( new RotateToDirection() );
emitter.addAction( new BoundingBox( -300, 300, -200, 200, -300, 300 ) );
emitter.addAction( new SpeedLimit( 100, true ) );
emitter.addAction( new SpeedLimit( 200 ) );
emitter.addAction( new Move() );

var renderer:DisplayObjectRenderer = new DisplayObjectRenderer( false );
renderer.x = 350;
renderer.y = 250;
renderer.addEmitter( emitter );
addChild( renderer );

renderer.camera.position = new Vector3D( 0, 0, -400 );
renderer.camera.target = new Vector3D( 0, 0, 0 );
renderer.camera.projectionDistance = 400;
var controller:FirstPersonCamera = new FirstPersonCamera( stage, renderer.camera );
controller.start();

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/flint3d"
  xmlns:geom="flash.geom.*"
  width="700" height="500"
  backgroundColor="#999999">

<f:DisplayObjectRenderer id="renderer" width="700" height="500">
  <f:camera>
    <f:Camera projectionDistance="400">
      <f:position>
        <geom:Vector3D x="0" y="0" z="-400"/>
      </f:position>
    </f:Camera>
  </f:camera>
  <f:emitters>
    <f:Emitter id="emitter" autoStart="true">
      <f:counter>
        <f:Blast startCount="300"/>
      </f:counter>
      <f:initializers>
        <f:Position>
          <f:BoxZone width="580" height="380" depth="580"/>
        </f:Position>
        <f:Velocity>
          <f:SphereZone innerRadius="100" outerRadius="150"/>
        </f:Velocity>
        <f:ImageClass imageClass="{Bird}"/>
      </f:initializers>
      <f:actions>
        <f:Move/>
        <f:SpeedLimit limit="200"/>
        <f:SpeedLimit limit="100" isMinimum="true"/>
        <f:ApproachNeighbours acceleration="100" maxDistance="200"/>
        <f:MatchVelocity acceleration="200" maxDistance="40"/>
        <f:MinimumDistance acceleration="600" minimum="20"/>
        <f:BoundingBox minX="-300" maxX="300" minY="-200" maxY="200" minZ="-300" maxZ="300"/>
        <f:RotateToDirection/>
      </f:actions>
    </f:Emitter>
  </f:emitters>
</f:DisplayObjectRenderer>
</s:Application>