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 termat 11 Feb 2010
/**
 * Copyright termat ( http://wonderfl.net/user/termat )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/nALB
 */

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);
			aq = new Aquarium(480, 480, 50);
			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 = 40.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);
			}
		}
	}
}