Forked from: wanson's Boid diff:156 forked from: Boid v21 forked:0favorite:0lines:206license : All rights reserved modified : 2010-01-13 01:16:09 Embed Tweet // forked from wanson's Boid package { import flash.display.Graphics; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.filters.*; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.text.TextFormat; import flash.ui.Mouse; [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(); private var m_as_boid:Boid = new Boid(); private var fold_sprite:Sprite = new Sprite(); private var fold:Fold = new Fold(); private var label:TextField = setupLabel(); private var customCursor:Sprite = new Sprite(); public function BoidDemo() { addEventListener(Event.ENTER_FRAME, onEnterFrame); stage.addEventListener(MouseEvent.MOUSE_MOVE, customCursorUpdate); var i:int; var g:Graphics = customCursor.graphics; g.lineStyle(1, 0xffff00); g.moveTo(0, 0); g.lineTo(-7, -3); g.lineTo(-7, 3); g.lineTo(0, 0); g.lineTo(-12, 0); addChild(customCursor); Mouse.hide(); this.mouseChildren = false; //stops us form getting text xursor over textfield 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); b.mouse = false; boids[i] = b; sprites[i] = new Sprite(); var g:Graphics = sprites[i].graphics; g.lineStyle(1, 0xffffff); g.moveTo(0, 0); g.lineTo(-7, -3); g.lineTo(-7, 3); g.lineTo(0, 0); g.lineTo(-12, 0); sprites[i].x = b.px; sprites[i].y = b.py; } var b:Boid = new Boid(); b.px = mouseX; b.py = mouseY; b.vy = 30 * (Math.random() - 0.5); b.vx = 30 * (Math.random() - 0.5); b.mouse = true; boids[NUMBOIDS - 1] = b; fold.centerx = 200; fold.centery = 200; fold.radius = 40; fold_sprite.graphics.lineStyle(1, 0xffffff); fold_sprite.graphics.drawCircle(0, 0, fold.radius); fold_sprite.x = fold.centerx; fold_sprite.y = fold.centery; this.addChild(fold_sprite); label.text = fold.boidsWithin(boids).toString(); fold_sprite.addChild(label); label.x = -1.75 * fold.radius; label.y = -fold.radius; label.scaleX = 5; label.scaleY = 5; for (i = 0; i < NUMBOIDS -1; i++) this.addChild(sprites[i]); //this.filters = [new GlowFilter(0xff5555, 1.0, 4, 4)]; } private function customCursorUpdate (ev:MouseEvent): void { customCursor.x = ev.stageX; customCursor.y = ev.stageY; customCursor.rotation = 225; } public function onEnterFrame(ev:Event) : void { frame(); } public function frame() : void { for (var i:int = 0; i < NUMBOIDS; i++) { var b:Boid = boids[i]; Mouse.hide(); m_as_boid.px = mouseX; m_as_boid.py = mouseY; b.force(boids); b.update(m_as_boid); sprites[i].x = b.px; sprites[i].y = b.py; sprites[i].rotation = Math.atan2(b.vy, b.vx) * 180 / Math.PI; var count:Number = fold.boidsWithin(boids); //if (count > 10) { //label.text = "LOSE"; //} //else { label.text = count.toString(); //} //fold.radius *= 1.000005; //fold_sprite.graphics.drawCircle(0, 0, fold.radius); //fold_sprite.scaleX += 0.000005; //fold_sprite.scaleY += 0.000005; } } public function setupLabel() : TextField{ var label:TextField = new TextField(); label.x = fold.radius; label.y = fold.radius; label.text = "GAME OVER"; label.textColor = 0xFFFFFF; label.addEventListener(MouseEvent.MOUSE_OVER, Mouse.hide); label.autoSize = TextFieldAutoSize.CENTER; label.width = 2; label.height = 1; return label } } } class ReplacementMouse { } class Fold { public var centerx:Number, centery:Number, radius:Number; public var count:Number; public function boidsWithin(boids:Array) : Number { var radius2:Number = radius * radius; var dx: Number, dy:Number, dist2:Number; var i:String; var count_local:Number = 0; for (i in boids){ dx = boids[i].px - centerx; dy = boids[i].py - centery; dist2 = dx * dx + dy * dy; if (dist2 < radius2) { count_local++; } } count = count_local; return (count_local); } } class Boid { public var px:Number, py:Number; public var vx:Number, vy:Number; public var mouse:Boolean; private var ax:Number, ay:Number; public function Boid() {} public function force(boids:Array) : void { // add mouse as a boid // 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 = 0, cy: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 if (!nearlest.mouse) { ax += (nvx - vx) * 0.2; ay += (nvy - vy) * 0.2; } // Cohesion dx = (cx/count - px); dy = (cy/count - py); //dy now redefined to average position of all boids within 1500 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; //lean to mouse } public function update(m_as_boid:Boid) : void { if (mouse == false) { px += vx * (1.0/12); py += vy * (1.0/12); vx += ax * (1.0/12); vy += ay * (1.0/12); } else { if ((vx != m_as_boid.vx) && (vy != m_as_boid.vy)) { vx = (m_as_boid.px - px) / 12.0; vy = (m_as_boid.py - py) / 12.0; } px = m_as_boid.px; py = m_as_boid.py; } // 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; } } } Code Fullscreen Preview Fullscreen Mouse.hide mouseChildren mouseY mouseX Number.MAX_VALUE Math.sqrt MouseEvent.MOUSE_OVER text stageY stageX rotation graphics MouseEvent.MOUSE_MOVE scaleY toString scaleX Math.atan2 height width MouseEvent.ENTER_FRAME