/**
* Copyright Nek ( http://wonderfl.net/user/Nek )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/hL5p
*/
package
{
import flash.display.Graphics;
import flash.display.Sprite;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.geom.Point;
[SWF(backgroundColor="0x000000",frameRate="31",width="300",height="300")]
public class Boids extends Sprite
{
public static const COUNT:int = 50;
public var positions1:Vector.<Point> = new Vector.<Point>(COUNT)
public var velocities1:Vector.<Point> = new Vector.<Point>(COUNT)
public var v11:Vector.<Point> = new Vector.<Point>(COUNT)
public var v12:Vector.<Point> = new Vector.<Point>(COUNT)
public var positions2:Vector.<Point> = new Vector.<Point>(COUNT)
public var velocities2:Vector.<Point> = new Vector.<Point>(COUNT)
public var v21:Vector.<Point> = new Vector.<Point>(COUNT)
public var v22:Vector.<Point> = new Vector.<Point>(COUNT)
public var positions3:Vector.<Point> = new Vector.<Point>(COUNT)
public var velocities3:Vector.<Point> = new Vector.<Point>(COUNT)
public var v31:Vector.<Point> = new Vector.<Point>(COUNT)
public var v32:Vector.<Point> = new Vector.<Point>(COUNT)
function Boids()
{
if (this.stage != null) init()
else addEventListener(Event.ADDED_TO_STAGE, init)
}
public function init():void
{
stage.scaleMode = StageScaleMode.NO_SCALE;
positions1.map(makePoint(300,300))
velocities1.map(makePoint(0,0))
positions2.map(makePoint(300,300))
velocities2.map(makePoint(0,0))
positions3.map(makePoint(300,300))
velocities3.map(makePoint(0,0))
addEventListener(Event.ENTER_FRAME, loop)
}
public function loop(e:Event = null):void
{
this.graphics.clear()
positions1.map(drawCircles)
v11.map(followMouse(positions1))
v12.map(keepDistance(10,positions1))
velocities1.map(add(v11))
velocities1.map(add(v12))
velocities1.map(limit(20))
positions1.map(add(velocities1))
positions2.map(drawCircles)
v21.map(followMouse(positions2))
v22.map(keepDistance(10,positions2))
velocities2.map(add(v21))
velocities2.map(add(v22))
velocities2.map(limit(20))
positions2.map(add(velocities2))
positions3.map(drawCircles)
v31.map(followMouse(positions3))
v32.map(keepDistance(10,positions3))
velocities3.map(add(v31))
velocities3.map(add(v32))
velocities3.map(limit(20))
positions3.map(add(velocities3))
}
public function drawCircles(item:Point, index:int, array:Vector.<Point>):void {
var g:Graphics = this.graphics
g.beginFill(0xaaaaaa)
g.drawCircle(item.x,item.y,2)
g.endFill()
}
public function makePoint(x:int,y:int):Function {
return function( item : Point, index : int,
array : Vector.<Point> ) : void
{
var p:Point = new Point(Math.random()*x, Math.random()*y)
array[index] = p
}
}
public function add(arr:Vector.<Point>):Function {
return function( item : Point, index : int,
array : Vector.<Point> ) : void
{
array[index].x += arr[index].x
array[index].y += arr[index].y
}
}
public function limit(num:int):Function {
return function( item : Point, index : int,
array : Vector.<Point> ) : void
{
var p:Point = array[index]
var s:Number = Math.sqrt( ( p.x * p.x + p.y * p.y ) )
if ( s > num )
{
p.x /= s
p.y /= s
p.x *= num
p.y *= num
}
}
}
public function sub(arr:Point):Function {
return function( item : Point, index : int,
array : Vector.<Point> ) : *
{
array[index] = new Point(array[index].x - arr.x, array[index].y - arr.y);
}
}
public function wrap( f : Function ) : Function
{
return(
function( p : Point, index : int, array : Vector.<Point> ) : *
{
return f( p )
}
)
}
public function allExcept( one : Point ) : Function
{
return(
function( p : Point ) : Boolean
{
return p != one
}
)
}
public function distanceIsCritical( target : Point , distance:int = 100 ) : Function
{
return(
function( p : Point ) : Boolean
{
var dx:Number = p.x - target.x;
var dy:Number = p.y - target.y;
return (dx * dx + dy * dy) < distance*distance
}
)
}
public function reduce(a:Vector.<Point>, reducer:Function):Point {
var result:Point = a[0]
for each(var p:Point in a.slice(1, a.length))
result = reducer(result, p)
return result
}
public function sum(p1:Point,p2:Point):Point {
return new Point(p1.x+p2.x,p1.y + p2.y)
}
public function seq_sub(c:Point,p:Point):Point {
return new Point(c.x - p.x,c.y - p.y)
}
public function followHive(pos:Vector.<Point>):Function {
return function( item : Point, index : int,
v1 : Vector.<Point> ) : void
{
var others:Vector.<Point> = pos.filter(wrap(allExcept(pos[index])))
var p:Point = reduce(others,sum)
p.x = (p.x/others.length - pos[index].x)/100
p.y = (p.y/others.length - pos[index].y)/100
v1[index] = p
}
}
public function followMouse(pos:Vector.<Point>):Function {
return function( item : Point, index : int,
v1 : Vector.<Point> ) : void
{
var p:Point = new Point();
p.x = (mouseX - pos[index].x)/100
p.y = (mouseY - pos[index].y)/100
v1[index] = p
}
}
public function keepDistance(num:Number,pos:Vector.<Point>):Function {
return function( item : Point, index : int,
rule : Vector.<Point> ) : void
{
var others:Vector.<Point> = pos.filter(wrap(allExcept(pos[index])))
var near:Vector.<Point> = others.filter(wrap(distanceIsCritical(pos[index],num)))
near.map(sub(pos[index]))
var result:Vector.<Point> = new Vector.<Point>
result[0] = new Point
rule[index] = reduce(result.concat(near),seq_sub)
}
}
}
}