/**
* 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();
}
}