In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Boid

Get Adobe Flash player
by bradsedito 06 Mar 2011
/**
 * Copyright bradsedito ( http://wonderfl.net/user/bradsedito )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/gleY
 */

// forked from termat's Boid
package
{
    import flash.display.BitmapData;
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.filters.BlurFilter;
    import flash.geom.ColorTransform;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    
    [SWF(width=480,height=480,backgroundColor=0x000000,frameRate=60)]
    public class Practice23 extends Sprite {
        private var bmpdata:BitmapData;
        private var bmp:Bitmap;
        private var colortrans:ColorTransform;
        private var filter:BlurFilter;
        private var aq:Aquarium;
        private var isDown:Boolean = false;
        private var pos:Point = new Point(0, 0);
        
        public function Practice23():void{
            bmpdata = new BitmapData( stage.stageWidth, stage.stageWidth, false, 0x000000);
            bmp = new Bitmap(bmpdata);
            addChild(bmp);
            colortrans = new ColorTransform( 0.95, 0.99, 0.99 );
            filter = new BlurFilter(2, 2, 1);
//  Setup   //
            aq = new Aquarium(480, 480, 850);
            //
            addEventListener(Event.ENTER_FRAME, update);
            stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
            stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove); 
        }
        
        private function update(e:Event):void {
            bmpdata.lock();
            bmpdata.applyFilter( bmpdata, bmpdata.rect, bmpdata.rect.topLeft, filter );
            bmpdata.colorTransform( bmpdata.rect, colortrans );
            aq.draw(bmpdata);
            bmpdata.draw(this);
            bmpdata.unlock();
            if (isDown) {
                aq.addBoid(pos.x,pos.y);
            }
        }
        
        private function mouseDown(e:MouseEvent):void {
            isDown = true;
            pos.x = e.stageX;
            pos.y = e.stageY;
        }
        
        private function mouseUp(e:MouseEvent):void {
            isDown = false;
        }
        
        private function mouseMove(e:MouseEvent):void {
            if (isDown) {
                pos.x = e.stageX;
                pos.y = e.stageY;
            }
        }
    }

}
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.display.BitmapData;
class Aquarium {
    private var bounds:Rectangle;
    public var list:Array;
    
    public function Aquarium(w:Number, h:Number, boidnum:int) {
        bounds=new Rectangle(0,0,w,h);
        Boid.aq = this;
        list = new Array();
        for (var i:int = 0; i < boidnum; i++) {
            addBoid(bounds.width * Math.random(),bounds.height * Math.random());
        }
    }
    
    public function draw(bmpdata:BitmapData):void {
        for each(var p:Boid in list) {
            p.setFriends(list);
        }
        for each(p in list) {
            p.update();
            bmpdata.setPixel( p.x, p.y, p.color );
            bmpdata.setPixel( (p.x * 0.9 + p.senser.x * 0.1), (p.y * 0.9 + p.senser.y * 0.1), p.color );
            bmpdata.setPixel( (p.x*0.8+p.senser.x*0.2), (p.y*0.8+p.senser.y*0.2), p.color );
        }
    }

    public function addBoid(xx:Number, yy:Number):void {
        if (list.length > 300) list.shift();
        var b:Boid = new Boid();
        b.x = xx;
        b.y = yy;
        b.dir = Math.PI * Math.random();
        list.push(b);
    }
    
    public function isOutOfBounds(p:Point, a:Boid):Boolean {
        return !bounds.containsPoint(p) || !bounds.contains(a.x, a.y);
    }

    public function isCollision(a:Boid):Boolean{
        for each(var o:Boid in list){
            if(a==o)continue;
            if (o.distance(a) <= a.size) {
                var tmp:Number = o.senser.x * a.senser.x + o.senser.y * a.senser.y;
                return tmp < 0;
            }
        }
        return false;
    }
}

class Boid {
    private const MAX_SPEED:Number = 3.2;
    private const MIN_SPEED:Number = 0.8;
    private const MAX_ACCEL:Number = 0.8;
    private const MAX_TURN:Number = 0.06;
    private const VIEW_DIST:Number = 50;
    private const VIEW_RAD:Number = 140.0/180.0*Math.PI;
    private const TWO_PI:Number=2.0*Math.PI;
    private const HALF_PI:Number=Math.PI/2.0;
    private const MIN_DIST:Number=30.0;
    public static  var aq:Aquarium=null;
    public var x:Number;
    public var y:Number;
    public var speed:Number=0.0;
    public var dir:Number=0.0;
    private var friends:Vector.<Boid>;
    public var size:Number = 10.0;
    public var color:uint = 0xffffff*Math.random();
    public var senser:Point;
    public var gene:Number;

    public function Boid():void{
        friends = new Vector.<Boid>();
        senser = new Point(0, 0);
        if (Math.random() <= 0.5) {
            gene=1.0;
        }else {
            gene = -1.0;
        }
    }
    
    public function numOfFriends():int {
        return this.friends.length;
    }
    
    public function distance(a:Boid):Number{
        var xx:Number=a.x-this.x;
        var yy:Number=a.y-this.y;
        return Math.sqrt(xx*xx+yy*yy);
    }
    
    private function alignment():void {
        if(friends.length<1) return;
        var avg:Number = 0;
        for each(var a:Boid in friends) {
            avg += a.speed;    
        }
        avg /= friends.length;
        if(speed<avg){
            speed -= MAX_ACCEL;
        }else{
            speed -= MAX_ACCEL;
        }
        speed = Math.max(MIN_SPEED, speed);
    }
    
    private function cohesion():void {
        if(friends.length<1){
            speed = Math.min(MAX_SPEED, speed + MAX_ACCEL);
            return;
        }
        var ax:Number = 0;
        var ay:Number = 0;
        for each(var a:Boid in friends) {
            ax += a.x;
            ay += a.y;    
        }
        ax /=friends.length;
        ay /=friends.length;
        var center:Number=Math.atan2(ay-y,ax-x);
        if(center<0)center=TWO_PI+center;
        center=center+HALF_PI-dir+VIEW_RAD/2;
        center = center % TWO_PI;
        if(center<0)center +=TWO_PI;
        if(center>VIEW_RAD/2.0){
            dir +=MAX_TURN;
        }else{
            dir -=MAX_TURN;
        }
      }
    
      private function  separation():void {
        if (friends.length < 1) return;
        var minlen:Number = 1000000;
        for each(var a:Boid in friends) {
            minlen=Math.min(minlen,this.distance(a));        
        }
        if(minlen<MIN_DIST){
            speed =Math.max(MIN_SPEED,speed-MAX_ACCEL);
        }
    }
    
    private function avoidance():void{
        updateSenser();
        if(aq.isOutOfBounds(senser,this)){
            dir +=MAX_TURN*gene;
        }else if(aq.isCollision(this)){
            dir -=MAX_TURN*gene;
        }
    }

    private function updateSenser():void {
        senser.x = x + size * Math.cos(dir);
        senser.y = y + size * Math.sin(dir);
    }
    
    public function update():void {
        separation();
        cohesion();
        alignment();
        updateSenser();
        avoidance();
        if (dir > TWO_PI) {
            dir -= TWO_PI;
        }else if (dir < 0) {
            dir += TWO_PI;
        }
        x += speed * Math.cos(dir);
        y += speed * Math.sin(dir);
    }

    public function setFriends(list:Array):void {
        while (friends.length > 0) friends.pop();
        for (var i:int = 0; i < list.length; i++) {
            if (list[i] == this) continue;
            checkFriend(list[i]);
        }
    }
    
    private function checkFriend(target:Boid):void {
        var len:Number = distance(target);
        if (len<=VIEW_DIST) {
            var a:Number=Math.atan2(target.y-this.y, target.x-this.x);
            if(a<0)a=TWO_PI+a;
            a = (a + HALF_PI - this.dir + VIEW_RAD / 2)%TWO_PI;
            if (a < 0) a += TWO_PI;
            if (a >= 0 && a <= VIEW_RAD) {
                friends.push(target);
            }
        }
    }
}