forked from: Constellation

by bradsedito forked from Constellation (diff: 5)
♥0 | Line 242 | Modified 2011-07-25 11:47:44 | MIT License
play

ActionScript3 source code

/**
 * Copyright bradsedito ( http://wonderfl.net/user/bradsedito )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/48By
 */

// forked from LawrieCape's Constellation
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 = 1;
        //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 = 0x555555;
        private var lineColour:uint = 0x999999;
        private var bgColour:uint   = 0xffffff;
        
        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;
        }
    }
}