/**
* Copyright LawrieCape ( http://wonderfl.net/user/LawrieCape )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/kH6Y
*/
package{
[SWF(width="465", height="465", frameRate="50")]
import flash.events.*;
import flash.events.KeyboardEvent;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.display.Stage;
import flash.geom.Point;
import flash.filters.BlurFilter;
import flash.filters.ColorMatrixFilter;
import flash.filters.ConvolutionFilter;
import flash.filters.GlowFilter
import flash.text.TextField;
import com.bit101.components.*;
public class BFCWonderfl extends MovieClip {
//Vars -
//You can play with these ones -
private var numBoids:int=20;
//Boids closer than this will feel crowded!
private var minDist:int=90;
//Boid further away than another than this will be lonely!
private var maxDist:int=100;
//This is how fast the boids can move. TOP SPEED!
private var maxSpeed:Number = 3;
//This is how much boids influence each other - lower number = more influence
private var divideBy:int=100;
//Shall the boids slow down with friction?
private var enableFriction:Boolean = true;
private var friction:Number = 0.9;
//Settle down - if they're not too close and not too far away from their friends - they'll just stop
private var settleDown:Boolean = false;
private var boidColour:uint = 0xffffff;
private var lineColour:uint = 0xffffff;
private var bgColour:uint = 0x000033;
private var glow:GlowFilter = new GlowFilter();
private var glowColour:uint = 0x99ffff;
//But you should probably leave these as is -
private var boidArray:Array=[];
private var menuHeight:Number = 85;
private var doMidi:Boolean = false;
private var BMD:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight-menuHeight, false, bgColour);
private var BF:BlurFilter = new BlurFilter(5,5,1);
private var Bit:Bitmap = new Bitmap(BMD);
private var bitHolder:MovieClip = new MovieClip;
private var ballHolder:MovieClip = new MovieClip;
private var isMouseDown:Boolean = false;
private var TB:TextField = new TextField();
private var myCheckBox1:CheckBox;
private var myCheckBox2:CheckBox;
private var mySlider1:HSlider;
private var mySlider2:HSlider;
//Boid Flock Class
public function BFCWonderfl():void{
trace("Init!");
addChild(bitHolder);
bitHolder.addChild(Bit);
addChild(ballHolder);
glow.color = glowColour;
glow.alpha = .5;
glow.blurX = 5;
glow.blurY = 5;
ballHolder.filters = [glow];
addChild(TB);
TB.y = 0;
TB.width = stage.stageWidth-10;
TB.height = 75;
TB.selectable = false;
TB.text = "Constellation by Lawrie\nhttp://www.LawrieCape.co.uk\nSpace to add a boid at mouse - click to attract - any other key to reset.\n\nADD MINIMAL COMPS HERE - MIN MAX sliders and Friction Settle checkboxes";
myCheckBox1 = new CheckBox(this,5,50,"Friction?",updateVals);
myCheckBox1.selected = true;
myCheckBox2 = new CheckBox(this,5,70,"Settle?",updateVals);
var sLabel:Label = new Label(this,75,45,"Min size");
var sLabel2:Label = new Label(this,75,65,"Max size");
mySlider1 = new HSlider(this,125,50,updateVals);
mySlider2 = new HSlider(this,125,70,updateVals);
mySlider1.setSliderParams(1,200,75);
mySlider2.setSliderParams(1,200,100);
addChild(myCheckBox1);
addChild(myCheckBox2);
addChild(mySlider1);
addChild(mySlider2);
bitHolder.y = menuHeight;
ballHolder.y = menuHeight;
ballHolder.mouseEnabled = false;
ballHolder.mouseChildren = false;
bitHolder.alpha=1;
BMD.fillRect(BMD.rect, bgColour);
bitHolder.addEventListener(MouseEvent.MOUSE_DOWN, mouseIsDown);
bitHolder.addEventListener(MouseEvent.MOUSE_UP, mouseIsNotDown);
stage.addEventListener(KeyboardEvent.KEY_UP, makeASingleBoid);
addEventListener(Event.ENTER_FRAME, updateBoids);
//makeBoids(numBoids);
}
private function makeASingleBoid(e:KeyboardEvent):void{
if(e.keyCode==32){
makeBoids(1,mouseX,mouseY);
}
else{
reset();
}
}
private function mouseIsDown(e:Event):void{
isMouseDown = true;
}
private function mouseIsNotDown(e:Event):void{
isMouseDown = false;
}
private function makeBoids(makeXBoids:int, bX:Number = 0, bY:Number = 0):void {
for (var i:int=0; i<makeXBoids; i++) {
var B:MovieClip = new MovieClip();
var bInner:MovieClip = new MovieClip();
//bInner.alpha=0.2;
bInner.graphics.beginFill(boidColour);
bInner.graphics.drawCircle(0,0,2);
B.addChild(bInner);
if(bX!=0){
B.x=bX;
}
else{
B.x=Math.random()*stage.stageWidth;
}
if(bY!=0){
B.y=bY-menuHeight;
}
else{
B.y=Math.random()*stage.stageHeight;
}
B.speedX = 0.1;
B.speedY = 0.1 ;
B.mouseEnabled = false;
B.mouseChildren = false;
boidArray.push(B);
ballHolder.addChild(B);
}
}
//Move -
private function updateBoids(e:Event):void {
for (var i:int=0; i<boidArray.length; i++) {
var B:*=boidArray[i];
var nearestBoid:*;
var nearestBoidNum:*;
var leastDist:int=1000;
B.distToB2X=0;
B.distToB2Y=0;
B.distToB2=0;
if(isMouseDown){
//Dont bother checking all the boids
}
else{
//This is not the best way of checking all the boids I'm sure, but it works fine for this little demo.
for (var j:int=0; j<boidArray.length; j++) {
var B2:*=boidArray[j];
if (B!=B2) {
var distX:Number=Math.round(B.x-B2.x);
var distY:Number=Math.round(B.y-B2.y);
var dist:Number = Math.round(Math.sqrt(((distX*distX)+(distY*distY))));
if (dist<leastDist) {
B.distToB2X=distX;
B.distToB2Y=distY;
B.distToB2=dist;
leastDist=dist;
nearestBoid=B2;
nearestBoidNum = j;
}
}
}
}
B.graphics.clear();
B.graphics.lineStyle(1,lineColour,0.5);
if(isMouseDown){
B.graphics.lineTo(mouseX-B.x,mouseY-(B.y+menuHeight));
B.distToB2X= Math.round(B.x-mouseX);
B.distToB2Y= Math.round((B.y+menuHeight)-mouseY);
B.distToB2 = Math.round(Math.sqrt(((B.distToB2X*B.distToB2X)+(B.distToB2Y*B.distToB2Y))));
}
else{
B.previousBoid = nearestBoid;
try{
B.graphics.lineTo(nearestBoid.x-B.x,nearestBoid.y-B.y);
}
catch(e:Error){
//Mouse down? Not enough Boids?
}
}
//1) If I am far away from my neighbors, move towards them.
if (B.distToB2>maxDist) {
B.speedX-=B.distToB2X/divideBy;
B.speedY-=B.distToB2Y/divideBy;
}
//2) If I am too close to my neighbors, move away from them.
else if (B.distToB2<minDist){
B.speedX+=B.distToB2X/divideBy;
B.speedY+=B.distToB2Y/divideBy;
}
//3) If I am neither too close or too far from my neighbors, move with them.
else if(settleDown){
//It's cool guys - we got away from them
B.speedX = 0;
B.speedY = 0;
}
//Bounce off the edges of the stage -
if (B.x>stage.stageWidth){
B.x=stage.stageWidth-B.speedX;
B.speedX*=-friction;
}
else if(B.x<0){
B.x=-B.speedX;
B.speedX*=-friction;
}
if (B.y>(stage.stageHeight-menuHeight)){
B.y=(stage.stageHeight-menuHeight)-B.speedY;
B.speedY*=-friction;
}
else if(B.y<0){
B.y=-B.speedY;
B.speedY*=-friction;
}
//Limit them to a top speed -
if(B.speedX>maxSpeed){
B.speedX = maxSpeed;
}
else if(B.speedX<-maxSpeed){
B.speedX=-maxSpeed;
}
if(B.speedY>maxSpeed){
B.speedY = maxSpeed;
}
else if(B.speedY<-maxSpeed){
B.speedY=-maxSpeed;
}
//Add friction?
if(enableFriction){
B.speedX*=friction;
B.speedY*=friction;
}
//Move them
B.x+=B.speedX;
B.y+=B.speedY;
}
//Draw into the BMD
BMD.draw(ballHolder);
//Apply a blur?
BMD.applyFilter(BMD,BMD.rect,new Point(0,0),BF);
}
private function reset():void{
removeEventListener(Event.ENTER_FRAME, updateBoids);
for (var i:int=0; i<boidArray.length; i++) {
var B:*=boidArray[i];
B.parent.removeChild(B);
B = null;
}
BMD.fillRect(BMD.rect, bgColour);
boidArray = [];
addEventListener(Event.ENTER_FRAME, updateBoids);
}
private function updateVals(e:Event):void{
//update!
enableFriction = myCheckBox1.selected;
settleDown = myCheckBox2.selected;
minDist = mySlider1.value;
maxDist = mySlider2.value;
}
private function map(v:Number, a:Number, b:Number, x:Number = 0, y:Number = 1):Number {
return (v == a) ? x : (v - a) * (y - x) / (b - a) + x;
}
}
}