package { import flash.display.Graphics; import flash.display.Sprite; import flash.events.Event; import flash.filters.*; [SWF(width="400", height="400", backgroundColor="0x000000")] public class BoidDemo extends Sprite { private const NUMBOIDS:int = 70; private var boids:Array = new Array(); private var sprites:Array = new Array(); public function BoidDemo() { addEventListener(Event.ENTER_FRAME, onEnterFrame); var i:int; for (i = 0; i < NUMBOIDS; i++) { var b:Boid = new Boid(); b.px = 400 * Math.random(); b.py = 400 * Math.random(); b.vx = 30 * (Math.random() - 0.5); b.vy = 30 * (Math.random() - 0.5); boids[i] = b; sprites[i] = new Sprite(); var g:Graphics = sprites[i].graphics; g.lineStyle(1, 0xffffff); g.moveTo(4, 0); g.lineTo(-3, -3); g.lineTo(-3, 3); g.lineTo(4, 0); g.lineTo(-8, 0); sprites[i].x = b.px; sprites[i].y = b.py; } for (i = 0; i < NUMBOIDS; i++) this.addChild(sprites[i]); //this.filters = [new GlowFilter(0xff5555, 1.0, 4, 4)]; } public function onEnterFrame(ev:Event) : void { frame(); } public function frame() : void { for (var i:int = 0; i < NUMBOIDS; i++) { var b:Boid = boids[i]; b.force(boids); b.update(); sprites[i].x = b.px; sprites[i].y = b.py; sprites[i].rotation = Math.atan2(b.vy, b.vx) * 180 / Math.PI; } } } } class Boid { public var px:Number, py:Number; public var vx:Number, vy:Number; private var ax:Number, ay:Number; public function Boid() {} public function force(boids:Array) : void { // find the nearlest neighbor var nearlest:Boid = null; var dx:Number, dy:Number; var dist2:Number; var mindist2:Number = Number.MAX_VALUE; var i:String; var b:Boid; var count:int = 0; var cx:Number = 0cy:Number = 0; for (i in boids) { b = boids[i]; if (b == this) continue; dx = b.px - px; dy = b.py - py; dist2 = dx * dx + dy * dy; if (dist2 < mindist2) { mindist2 = dist2; nearlest = b; } if (dist2 < 1500) { cx += b.px; cy += b.py; count++; } } if (nearlest == null) return; ax = ay = 0; var npx:Number = nearlest.px; var npy:Number = nearlest.py; var nvx:Number = nearlest.vx; var nvy:Number = nearlest.vy; dx = (npx - px); dy = (npy - py); dist2 = dx * dx + dy * dy; if (dist2 > 1500) return; // Separation var dist:Number = Math.sqrt(dist2); ax += dx / dist * (dist - 25) * 0.5; ay += dy / dist * (dist - 25) * 0.5; // Alignment ax += (nvx - vx) * 0.2; ay += (nvy - vy) * 0.2; // Cohesion dx = (cx/count - px); dy = (cy/count - py); ax += dx * 0.1; ay += dy * 0.1; ax += 10 * (Math.random() - 0.5); ay += 10 * (Math.random() - 0.5); // boundary if (px < 50) ax += (50 - px) * 0.05; else if (px > 350) ax += (350 - px) * 0.05; if (py < 50) ay += (50 - py) * 0.05; else if (py > 350) ay += (350 - py) * 0.05; } public function update() : void { px += vx * (1.0/12); py += vy * (1.0/12); vx += ax * (1.0/12); vy += ay * (1.0/12); // speed limit var v:Number = Math.sqrt(vx * vx + vy * vy); if (v > 17) { vx = vx / v * 17; vy = vy / v * 17; } else if (v < 8) { vx = vx / v * 8; vy = vy / v * 8; } } } Boid