forked from: boid(精子風味)

by yamat1011 forked from boid(精子風味) (diff: 1)
♥0 | Line 197 | Modified 2011-02-18 22:12:02 | MIT License
play

ActionScript3 source code

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

// forked from satoru.net's boid(精子風味)
package {
    
import com.bit101.components.*;
import flash.display.*;
import flash.events.*;
import flash.utils.*;
import flash.geom.*;
[SWF(width="500", height="500", frameRate="100")]

public class main extends Sprite{
    var NUM_BOIDS:int = 30;
    var DIST_THRESHOLD1:int = 10;
    var DIST_THRESHOLD2:int = 20;
    var DIST_THRESHOLD3:int = 30;
    var FACTOR_COHESION = 100;
    var FACTOR_SEPARATION = 10;
    var FACTOR_ALINGMENT = 10;
    var VELOCITY_LIMIT = 3;
    var TRAIL_SCALE = 2;
    var prePosLength = 10;
    var flock:Array;
    var sh = new Sprite();
    var bmp = new Bitmap(new BitmapData(500,500,true,0x000000));
    var black = new BitmapData(500, 500, false, 0x000000);
    var gr = sh.graphics;

    function main() {
        addChild(sh);
        addChild(bmp);
        init();
        addEventListener(Event.ENTER_FRAME, interval);
        stage.addEventListener(MouseEvent.MOUSE_DOWN, doReset);
    }

    function init(){
        flock = new Array();
        for(var n=0;n<NUM_BOIDS;n++){
            var b = Boid();
            flock.push(b);
        }    
    }

    function setValue(key,val){
        for(var i in flock){
            flock[i][key] = val;
        }
    }

    function doReset(e:*){
        for(var i in flock){
            flock[i].remove();
            flock[i] = null;
        }    
        init();
    }

    function interval(e:*) {
        bmp.bitmapData.draw(black);
        for(var i in flock){
            flock[i].update();
        }
    }

    function getRandom(low,high){
        return low+Math.floor(Math.random()*((high-low)));
    }

    function Boid(){
        var r1 = 1.0 //cohesion.value; // Cohesion:   pull to center of flock
        var r2 = 0.8 //separation.value; // Separation: avoid bunching up
        var r3 = 0.1 //alingment.value; // Alingment:  match average flock speed
        
        var o = {
            "shape":new Shape(),
            "v1":Vector(),
            "v2":Vector(),
            "v3":Vector(),
            "r1":r1,
            "r2":r2,
            "r3":r3,
            "vx":getRandom(-5, 5),
            "vy":getRandom(-5, 5),
            "xpos":getRandom(0,stage.stageWidth),
            "ypos":getRandom(0,stage.stageHeight),
            "prePos":new Array()
        };
        
        init();
        
        function init(){
            //o.gr = sh.graphics;
            o.gr = o.shape.graphics;
            return o;
        }
        
        o.remove = function(){
            o = null;
            return;
        }
        
        o.update = function(){
            updatePosition(); 
            savePosition();
            drawPoint();
         }  
            
        function savePosition(){
            o.prePos.unshift({x:o.xpos,y:o.ypos});

            if(o.prePos.length >prePosLength){
                o.prePos.length = prePosLength;
            }
        }
        
      function drawPoint(){
        o.gr.clear();
        o.gr.lineStyle(4,0xFFFFFF);      

        o.gr.moveTo(o.xpos, o.ypos);
        o.gr.lineTo(o.xpos-TRAIL_SCALE*o.vx, o.ypos-TRAIL_SCALE*o.vy);

        for(var i in o.prePos){    
            var X = o.prePos[i].x;
            var Y = o.prePos[i].y;
            
            o.gr.lineStyle(1,0xFF00000);    
            o.gr.moveTo(X, Y);
            o.gr.lineTo(X-TRAIL_SCALE*o.vx, Y-TRAIL_SCALE*o.vy);
        }    
        
        bmp.bitmapData.draw(o.shape);
      }    

      function limitVelocity(){
       var velocity = Math.sqrt(Math.pow(o.vx,2) + Math.pow(o.vy,2));
        if(velocity > VELOCITY_LIMIT){
          o.vx = (o.vx/velocity)*VELOCITY_LIMIT;
          o.vy = (o.vy/velocity)*VELOCITY_LIMIT;
        }
      }
      
      function updatePosition(){
        if(o.isStop){
            return;
        }
          
        o.v1.x = o.v1.y = o.v2.x = o.v2.y = o.v3.x = o.v3.y = 0;
        rule1();
        rule2();    
        rule3();
        
        // add vectors to velocities
        o.vx += o.r1*o.v1.x + o.r2*o.v2.x + o.r3*o.v3.x;
        o.vy += o.r1*o.v1.y + o.r2*o.v2.y + o.r3*o.v3.y;
        
        limitVelocity();
        
        o.xpos += o.vx;
        o.ypos += o.vy;
        
        if(o.xpos < 0){
          o.xpos = stage.stageWidth;
        } else if(o.xpos > stage.stageWidth){
          o.xpos = 0;
        }
        if(o.ypos < 0){
          o.ypos = stage.stageHeight;
        } else if(o.ypos > stage.stageHeight){
          o.ypos = 0;
        }
      }  

      // Cohesion
      function rule1(){
        var count = 0;
        
        for(var i in flock){
          if(o !== flock[i]){
            var len = Point.distance(new Point(o.xpos, o.ypos), new Point(flock[i].xpos, flock[i].ypos));
            if(len > DIST_THRESHOLD2 && len < DIST_THRESHOLD3){
              o.v1.x += flock[i].xpos;
              o.v1.y += flock[i].ypos;
              count++;
            }
          }
        }
        
        if(count > 0){
          o.v1.x /= count;
          o.v1.y /= count;
          o.v1.x = (o.v1.x - o.xpos) / FACTOR_COHESION;
          o.v1.y = (o.v1.y - o.ypos) / FACTOR_COHESION;
        }
      }

       function rule2(){
        for(var i in flock){
          if(o !== flock[i]){
            var len = Point.distance(new Point(o.xpos, o.ypos), new Point(flock[i].xpos, flock[i].ypos));
            if(len < DIST_THRESHOLD1){
              o.v2.x -= (flock[i].xpos - o.xpos)/FACTOR_SEPARATION;
              o.v2.y -= (flock[i].ypos - o.ypos)/FACTOR_SEPARATION;
            }
          }
        }
      } 

      // Alingment()
      function rule3(){
        var count = 0;
        for(var i in flock){
          if(o !== flock[i]){
            var len = Point.distance(new Point(o.xpos, o.ypos), new Point(flock[i].xpos, flock[i].ypos));
            if(len > DIST_THRESHOLD1 && len < DIST_THRESHOLD2){
              o.v3.x += flock[i].vx;
              o.v3.y += flock[i].vy;
              count++;
            }
          }
        }
        if(count > 0){
          o.v3.x /= count;
          o.v3.y /= count;
          o.v3.x = (o.v3.x - o.vx)/FACTOR_ALINGMENT;
          o.v3.y = (o.v3.y - o.vy)/FACTOR_ALINGMENT;
        }
      }  
      return o;  
    }

    function Vector(){
        return {x:0,y:0};
    }

}
}