flash on 2010-5-2

by shohei909
LIVE CODING 2010/05/02 11:00-
物理シュミレート的なことをやる
♥0 | Line 238 | Modified 2010-05-02 21:24:21 | MIT License
play

ActionScript3 source code

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

//LIVE CODING 2010/05/02 11:00-
//物理シュミレート的なことをやる

package {
    import flash.display.Sprite;
	import flash.events.Event;
    import flash.events.MouseEvent;
    import com.bit101.components.FPSMeter;
    import com.bit101.components.Label;
    
    [SWF(backgroundColor="#ffffff", frameRate=30)] 
    public class FlashTest extends Sprite {
    		private var physicalStage:PhysicalStage;
    		private var vectorShape:VectorShape = new VectorShape();
    		private var isDown:Boolean = false;
    		private var downX:Number;
    		private var downY:Number;
    		
    		private var label:Label;
    		private var sp:Spring;
    		
        public function FlashTest() {
            physicalStage = new PhysicalStage(465,465);
            stage.addChild( physicalStage );
            stage.addChild( vectorShape );
           	label = new Label(stage,0,10,"click to place object");
           	new FPSMeter(stage,0,0);
           	
            
            stage.addEventListener( "mouseUp", up);
            stage.addEventListener( "mouseDown", down);
            stage.addEventListener( "mouseMove", move);
            
       		var dot1:PhysicalDot = new PhysicalDot(100,100,false,0,0);
       		var dot2:PhysicalDot = new PhysicalDot(100,121);
       		dot2.fix = true ;
       		
       		physicalStage.addChild(  dot1 );
       		physicalStage.addChild(  dot2 );
       		sp = dot1.connect(dot2);
       		physicalStage.addChild(  sp );
       }
       public function up(e:MouseEvent):void{
       		if(isDown){
       			isDown = false;
       			var vx:Number = 0;
       			var vy:Number = 0;
       			if(e.localX == downX && e.localY == downY ){
       				var deg:Number = Math.random()*Math.PI*2;
					vx = 3 * Math.sin(deg);
					vy = 3 * Math.cos(deg);
       			}else{
       				vx = 0.05 * (downX - e.localX);
					vy = 0.05 * (downY - e.localY);
       			}
       			
       			physicalStage.addChild(  new PhysicalDot(e.localX,e.localY,false,vx,vy) );
       		
    				vectorShape.visible = false;
       		}
       }
       
       public function down(e:MouseEvent):void{
       		isDown = true;
       		downX = e.localX;
       		downY = e.localY;
    			with(vectorShape){
    				startX = downX;
    				startY = downY;
    				endX = downX;
    				endY = downY;
    			}
       }
       
       public function move(e:MouseEvent):void{
	      if(isDown){
	    			with(vectorShape){
		    			visible = true;
	    				startX = e.localX;
	    				startY = e.localY;
	    				draw();
	    			}
	       }
       }
       
       
    }
   
   
}









import flash.display.*;
import flash.events.Event;
import flash.geom.*;
import flash.filters.*;

class VectorShape extends Shape{
	public var startX:Number; 
	public var startY:Number; 
	public var endX:Number; 
	public var endY:Number; 
	public function draw():void{
		graphics.clear();
		graphics.lineStyle(1,0xFFAACC,1.0);
		graphics.moveTo(startX,startY);
		graphics.lineTo(endX,endY);
	}
}





//物理法則にしたがった物体を配置するためのステージ
class PhysicalStage extends Bitmap{
	public var backgroundColor:uint = 0x000000;
	
	public var children:Vector.<PhysicalObject> = new Vector.<PhysicalObject>();
	public var margin:int = 500;//childrenのはみ出しをどれだけ許すか
	
	
	//ステージ上の重力
	public var gravity:Array = [0, 0];
	
	//フィルター
	public var disolveFilters:Array = [new BlurFilter(2,2,1)];
	
	
	
	
	public function PhysicalStage(w:int,h:int){
		super( new BitmapData( w,h,false, backgroundColor) );
		addEventListener(Event.ENTER_FRAME, onFrame);
	}
	
	public function addChild(child:PhysicalObject):void{
		children.push(child);
	}
	
	
	
	private function onFrame(e:Event):void{
		var b:BitmapData = bitmapData;
		for each(var filter:BlurFilter in disolveFilters ){
			b.applyFilter(b,b.rect,new Point(0,0),filter);
		}
		b.draw( new BitmapData(b.width,b.height,true, 0x1000000 + backgroundColor ),null,null, "shader" );
		
		
		
		
		var rect:Rectangle = new Rectangle(-margin,-margin,bitmapData.width+margin*2,bitmapData.height+margin*2)
		var l:int = children.length;
		for(var i:int = 0; i<l;i++){
			var child:PhysicalObject = children[i];
			child.draw(bitmapData);
			child.accel( gravity[0],gravity[1] );
			child.frame();
			child.move();
			
			//余白より外に出ている場合は消去
			if( rect.contains(child.x,child.y) == false){
				children.splice(i,1);
			}
		}
	}
}

class PhysicalObject{
	//座標
	public var x:Number;
	public var y:Number;
	public var nextX:Number;
	public var nextY:Number;
	
	public var visible:Boolean;	//表示するか
	public var fix:Boolean;	//固定するか
	public var touchable:Boolean;
	
	public var color:uint;		//色
	
	
	//マップにこのオブジェクトを書き込む
	public function draw(map:BitmapData):void{}
	public function collide(c:Vector.<PhysicalObject>):void{}
	public function move():void{}	
	public function frame():void{}
	public function accel( ax:Number,ay:Number ):void{}
	public function gravitate( _x:Number,_y:Number,g:Number,loss:Boolean  = false):void{}
}


class PhysicalDot extends PhysicalObject{
	//速度
	public var vx:Number;
	public var vy:Number;
	
	
	
	public var m:Number;//質量
	
	
	//この点を始点とするばね 
	public var springs:Vector.<Spring> = new Vector.<Spring>();
	
	public function PhysicalDot(  _x:Number = 0,  _y:Number = 0  , _fix:Boolean = false, _vx:Number = 0,  _vy:Number = 0, _m:Number=1, _visible:Boolean = true, _color:uint = 0xFF6666 ){
		nextX = _x;
		nextY = _y;
		x = nextX;
		y = nextY;
		fix = _fix;
		m = _m;
		vx = _vx;
		vy = _vy;
		visible = _visible;
		color = _color;
	}
	
	
	
	public override function draw(map:BitmapData):void{
		if( visible == true ){
			map.setPixel(x,y,color);
		}
	}
	
	
	public override function move():void{
		if(fix == false){ 
			x = nextX;
			y = nextY;
			nextX += vx;
			nextY += vy;
		}
	}
	
	
	public override function accel(ax:Number,ay:Number):void{
		if(fix == false){ 
			vx += ax;
			vy += ay;
		}
	}
	public function  pull( fx:Number,fy:Number ):void{
		if(fix == false){ 
			vx += fx/m;
			vy += fy/m;
		}
	}
	
	
	public override function gravitate(_x:Number,_y:Number,_g:Number,loss:Boolean = false):void{
		if(fix == false){ 
			var deg:Number = Math.atan2( _x-x , _y-y );
			if(loss){
				var l:Number = Point.distance( new Point(_x,_y),new Point(x,y) );
				vx += _g * Math.sin(deg);
				vy += _g * Math.cos(deg);
			}else{
				vx += _g * Math.sin(deg);
				vy += _g * Math.cos(deg);
			}
		}
	}
	
	//
	public function connect(dot:PhysicalDot, l:Number=20.0,k:Number=0.01):Spring{
		var s:Spring = new Spring(this,dot,l,k);
		return s;
	}
	
}


class Spring extends PhysicalObject{
	public var start:PhysicalDot;
	public var end:PhysicalDot;
	
	public var length:Number;	//自然長
	public var k:Number;		//ばね定数
	
	public function Spring(dot1:PhysicalDot,dot2:PhysicalDot,l:Number=1.0,_k:Number=1.0):void{
		start = dot1;
		end = dot2;
		length = l;
		k = _k;
	}
	

	public override function move():void{
		var deg:Number = Math.atan2( start.x-end.x , start.y-end.y );
		var l:Number = Point.distance( new Point(start.x,start.y), new Point(end.x,end.y) );
		var f:Number = k * (l-length) ;
		
		
		start.pull(-f * Math.sin(deg), -f * Math.cos(deg));
		end.pull(f * Math.sin(deg), f * Math.cos(deg));
		
		x = start.x;
		y = start.y;
		nextX = start.x;
		nextY = start.y;
	}
	
}

//重力をもった点
class Planet extends PhysicalDot{
	public var gravity:Number;
	public var gChildren:Vector.<PhysicalObject>;
	
	//力の減衰があるか
	public var loss:Boolean = true;
	
	public function Planet(  c:Vector.<PhysicalObject>, g:Number = 0.1, _x:Number = 0,  _y:Number = 0  , _fix:Boolean = false, _vx:Number = 0,  _vy:Number = 0, _m:Number=10000, _visible:Boolean = true, _color:uint = 0x6666FF ){
		super( _x, _y, _fix, _vx, _vy, _m, _visible, _color);
		gravity = g;
		gChildren = c;
	}
	
	public override function move():void{
		for each( var child:PhysicalObject in gChildren ){
			if(child != this){
				child.gravitate(x,y,gravity,loss);
			}	
		}
		super.move();
	}
}