In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

wonderfl用Box2Dテンプレートを作ってみたい。Ver0.2

wonderfl用Box2Dテンプレートを作ってみたい。Ver0.2

多角形作成関数と、距離ジョイント・回転ジョイント・直動ジョイント関数を作ってみた。
なんとなく概念はわかってきたけど、慣れが必要だなぁ。

最近少し忙しいのでちょこちょことやる予定。
Box2Dはいろいろ手続きが面倒すぎるので、楽しいところだけ弄れるようにしたい。

ここを大いに参考にしてるというか、ほぼそのままで、拡張中。
http://hokori.net/2009/02/18/box2dflashas3_base/
Get Adobe Flash player
by Hiiragi 16 Jul 2009
package  
{
	import flash.display.Sprite;
	import Box2D.Collision.*;
	import Box2D.Common.Math.*;
	import Box2D.Dynamics.*;
	import Box2D.Dynamics.Joints.*;
	import Box2D.Collision.Shapes.*;
	import flash.events.Event;

	/**
	 * wonderfl用Box2Dテンプレートを作ってみたい。Ver0.2
	 * 
	 * 多角形作成関数と、距離ジョイント・回転ジョイント・直動ジョイント関数を作ってみた。
	 * なんとなく概念はわかってきたけど、慣れが必要だなぁ。
	 * 
	 * 
	 * 最近少し忙しいのでちょこちょことやる予定。
	 * Box2Dはいろいろ手続きが面倒すぎるので、楽しいところだけ弄れるようにしたい。
	 * 
	 * ここを大いに参考にしてるというか、ほぼそのままで、拡張中。
	 * http://hokori.net/2009/02/18/box2dflashas3_base/
	 */
	[SWF(width=465,height=465,frameRate=60,backgroundColor=0x000000)]
	public class Test extends Sprite
	{
		//固定プロパティ
		private var _world:b2World;
		private var _catalystObj:B2DCatalyst;
		
		//設定用プロパティ
		private const WIDTH:Number = 465;
		private const HEIGHT:Number = 465;
		private var _fps:Number = 60;
		private var _timeStep:Number = 1.0 / _fps;
		private var _scale:Number = 100;
		private var _gravity:Number = 10;
		
		//各自追加プロパティ
		private var cnt:Number = 0;
		
		private var _prismaticLiftBody:b2Body;
		private var _prismaticLiftJoint:b2PrismaticJoint;
		
		
		
		public function Test() 
		{
			init();
		}
		
		private function init():void {
			_catalystObj = new B2DCatalyst(true, _fps, _scale, _gravity);
			this.addChild(_catalystObj);
			_world = _catalystObj.world;
			
			////////////////////////////////////////////////
			////////////	以下、設定用コード		////////////
			////////////////////////////////////////////////
			
			//床を作成
			_catalystObj.makeB2BodyBox(465, 30, 232.5, 435, 0, 0, 0.5, 0.5);
			
			//多角形を作ってみる
			_catalystObj.makeB2BodyPolygon(220, 200, [[0.0, 0.0], [25, 25], [25, 50],[-25, 50],[-25, 25]], 0, 0.2, 0.5);
			
			//距離ジョイントを使って二つの物体を結びつける
			var dJObj1:b2Body = _catalystObj.makeB2BodyBox(40, 40, 150, 100, 0, 1, 0.5, 0.5);
			var dJObj2:b2Body = _catalystObj.makeB2BodyBox(40, 40, 250, 100, 0, 1, 0.5, 0.5);
			var anchor1:b2Vec2 = _catalystObj.createB2Vec(dJObj1.GetPosition().x*_scale, dJObj1.GetPosition().y*_scale);
			var anchor2:b2Vec2 = _catalystObj.createB2Vec(dJObj2.GetPosition().x*_scale, dJObj2.GetPosition().y*_scale);
			
			_catalystObj.makeDistanceJoint(dJObj1, dJObj2, anchor1, anchor2);
			
			//回転ジョイント
			var rJObj1:b2Body = _catalystObj.makeB2BodyCircle(50,400,150,0,0,0);
			var rjObj2:b2Body = _catalystObj.makeB2BodyBox(40, 40, 400, 200, 0, 1, 0.5, 0.5);
			var anchor:b2Vec2 = _catalystObj.createB2Vec(rJObj1.GetPosition().x*_scale, rJObj1.GetPosition().y*_scale); 
			_catalystObj.makeRevoluteJoint(rJObj1, rjObj2, anchor,true,100,1,true,0,120);
			
			//直動ジョイント
			var pJ_anchorObj:b2Body = _world.GetGroundBody();
			var pJ_moveObj:b2Body = _catalystObj.makeB2BodyBox(60, 10, 200, 300, 0, 1, 0.5, 0.5);
			var pJ_moveObjAnchor:b2Vec2 = _catalystObj.createB2Vec(pJ_moveObj.GetPosition().x*_scale,pJ_moveObj.GetPosition().y*_scale);
			var pJ_Vector:b2Vec2 = new b2Vec2(1.0, 0);
			
			_prismaticLiftJoint = _catalystObj.makePrismaticJoint(pJ_anchorObj, pJ_moveObj, pJ_moveObjAnchor, pJ_Vector);
			_prismaticLiftBody = pJ_moveObj;

			////////////////////////////////////////////////
			////////////	以上、設定用コード		////////////
			////////////////////////////////////////////////
			_catalystObj.addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
		}
		
		private function onEnterFrameHandler(e:Event):void 
		{
			_world.Step(_timeStep, 10);
			
			////////////////////////////////////////////////
			////////////	以下、描画更新用コード	////////////
			////////////////////////////////////////////////
			
			//30フレームごとに四角と丸を作る
			if (cnt == 30) {
				create();
				cnt = 0;
			} else {
				cnt++;
			}
			
			//直動ジョイント制御
			var pj_PosX:Number = _prismaticLiftBody.GetPosition().x * _scale;
			var pj_SpeedX:Number = _prismaticLiftJoint.GetMotorSpeed();

			if (pj_PosX > 400 && pj_SpeedX > 0) {
				_prismaticLiftJoint.SetMotorSpeed(pj_SpeedX * -1);
			} else if (pj_PosX < 100 && pj_SpeedX < 0) {
				_prismaticLiftJoint.SetMotorSpeed(pj_SpeedX * -1);
			}
			////////////////////////////////////////////////
			////////////	以上、描画更新用コード	////////////
			////////////////////////////////////////////////
			
			//画面外に行ったオブジェクトを削除する
			var marginX:Number = 50;
			var marginY:Number = 50;
			for (var b:b2Body = _world.GetBodyList(); b; b = b.GetNext()) {
				var xPos:Number = b.GetWorldCenter().x * _scale;
				var yPos:Number = b.GetWorldCenter().x * _scale;
				if (xPos > WIDTH + marginX || xPos < -marginX || yPos > HEIGHT + marginY || yPos < -marginY){
					_world.DestroyBody(b);
				}
			}
		}
		
		
		
		private function create():void {
			_catalystObj.makeB2BodyCircle(50, Math.random() * 465, 0, 1, 0.2, 0.5);
			_catalystObj.makeB2BodyBox(50, 50, Math.random() * 465, 0, Math.random() * Math.PI * 2, 1, 0.2, 0.5);
		}
	}
	
}













//以下、媒介用クラス。なので、拡張する時以外、通常弄る必要なし
//以下のURLをほぼ丸ごと。少しずつ拡張予定。
//http://hokori.net/2009/02/18/box2dflashas3_base/


import flash.display.Sprite;
import flash.geom.Point;

import Box2D.Collision.*;
import Box2D.Common.Math.*;
import Box2D.Dynamics.*;
import Box2D.Dynamics.Joints.*
import Box2D.Collision.Shapes.*;

internal class B2DCatalyst extends Sprite
{
    //Box2Dのバージョンは2.0.2

    private var m_b2_world:b2World;
    //縮尺 1mを何ピクセルで表すか
    private var m_b2_physcale:Number = 10;  
    //演算制度 大きいと正確だけど、負荷が大きい
    private var m_b2_iterations:int = 10;   
    // 演算をfpsに合わせる
    private var m_b2_timeStep:Number = 24.0;  
    
	
    //constructor
    public function B2DCatalyst(debugModeFlag:Boolean = false, fps:int = 24, 
								physcale:Number = 10, gravity:Number = 10):void{
        
        //timestep設定
        this.m_b2_timeStep = 1.0 / fps;
        
        //スケール設定
        this.m_b2_physcale = physcale;
        
        //B2DBoxの世界生成
        this.createB2World(gravity);
		
		//debugMode
		if (debugModeFlag) startDebugMode();
    }

    //Box2D世界作成
    private function createB2World(gravity:Number):void {
        
        // Creat world AABB
        var worldAABB:b2AABB = new b2AABB();
        worldAABB.lowerBound.Set(-1000, -1000);
        worldAABB.upperBound.Set(1000, 1000);
        
        // Define the gravity vector
        var vec_gravity:b2Vec2 = new b2Vec2(0.0, gravity);
        
        // Allow bodies to sleep
        var doSleep:Boolean = true;
        
        // Construct a world object
        this.m_b2_world = new b2World(worldAABB, vec_gravity, doSleep);
    }
    
    
	
	
    /**
     * 長方形の物体作成
     * @param   int w (ピクセル 内部でB2DBox用に変換)
     * @param   int h (ピクセル 内部でB2DBox用に変換)
     * @param   Number x(ピクセル 内部でB2DBox用に変換)
     * @param   Number y(ピクセル 内部でB2DBox用に変換)
     * @param   Number angle 角度(360度 内部でラジアンに変換)
     * @param   density 密度 0にすると固定
     * @param   friction 摩擦 大きいと滑りにくい
     * @param   restitution 跳ね返り 大きいと、反発しやすい
     * @param   viewdata 表示用のSprite
     * @param   viewgroup 表示用のSpriteを入れるSprite
     * @return  b2Body
     */
    public function makeB2BodyBox(w:int, h:int,
                     x:Number, y:Number, angle:Number, 
                     density:Number,
                     friction:Number,
                     restitution:Number,
                     viewdata:Sprite = null,
                     viewgroup:Sprite = null) :b2Body {
		
        var b2_boxdef:b2PolygonDef = this.createB2BoxDef(w, h, density,
                                 friction, restitution);
        var b2_bodydef:b2BodyDef = this.createB2BodyDef(x, y, w, h, angle,
                                viewdata, viewgroup);
        
        var b2_body:b2Body = this.m_b2_world.CreateBody(b2_bodydef);
        b2_body.CreateShape(b2_boxdef);
        b2_body.SetMassFromShapes();
        
        return b2_body;
    }   
	
	
    /**
     * 多角形の物体作成
     * @param   int w (ピクセル 内部でB2DBox用に変換)
     * @param   int h (ピクセル 内部でB2DBox用に変換)
     * @param   Number x(ピクセル 内部でB2DBox用に変換)
     * @param   Number y(ピクセル 内部でB2DBox用に変換)
     * @param   Number angle 角度(360度 内部でラジアンに変換)
     * @param   density 密度 0にすると固定
     * @param   friction 摩擦 大きいと滑りにくい
     * @param   restitution 跳ね返り 大きいと、反発しやすい
     * @param   viewdata 表示用のSprite
     * @param   viewgroup 表示用のSpriteを入れるSprite
     * @return  b2Body
     */
    public function makeB2BodyPolygon(x:Number, y:Number, vertex:Array, 
                     density:Number,
                     friction:Number,
                     restitution:Number,
                     viewdata:Sprite = null,
                     viewgroup:Sprite = null) :b2Body {
		
        var b2_bodydef:b2BodyDef = new b2BodyDef();
		b2_bodydef.position.Set(x / m_b2_physcale, y / m_b2_physcale);
		
        var b2_Polydef:b2PolygonDef = new b2PolygonDef();
		var len:int = b2_Polydef.vertexCount = vertex.length;

		for (var i:int = 0; i < len; i++) {
			b2_Polydef.vertices[i].Set(vertex[i][0]/m_b2_physcale, vertex[i][1]/m_b2_physcale);
		}
        b2_Polydef.density = density;
		b2_Polydef.friction = friction;
		b2_Polydef.restitution = restitution;
		
        var b2_body:b2Body = this.m_b2_world.CreateBody(b2_bodydef);
        b2_body.CreateShape(b2_Polydef);
        b2_body.SetMassFromShapes();
        
        return b2_body;
    }   
    
    
    /**
     * 円の物体作成
     * @param   diameter 直径(ピクセル 内部でメートルに変換)
     * @param   x (ピクセル 内部でメートルに変換)
     * @param   y(ピクセル 内部でメートルに変換)
     * @param   density 密度 0にすると固定 大きいと、ぶつかったとき強い
     * @param   friction 摩擦 大きいと滑りにくい
     * @param   restitution 跳ね返り 大きいと、反発しやすい
     * @param   viewdata 表示用のSprite
     * @param   viewgroup 表示用のSpriteを入れるSprite
     * @return  b2Body
     */
    public function makeB2BodyCircle(diameter:int, x:Number, y:Number, 
                    density:Number,
                    friction:Number,
                    restitution:Number,
                    viewdata:Sprite = null,
                    viewgroup:Sprite = null) :b2Body {
        
        var b2_boxdef:b2CircleDef = this.createB2CircleDef(diameter,
                            density, friction, restitution);

        var b2_bodydef:b2BodyDef = this.createB2BodyDef(x, y, 0, 0, 0,
                            viewdata, viewgroup);
        
        var b2_body:b2Body = this.m_b2_world.CreateBody(b2_bodydef);
        b2_body.CreateShape(b2_boxdef);
        b2_body.SetMassFromShapes();
        
        return b2_body;
    }
    
    
    /**
     * 長方形の性質設定(形状と素材)
     * @param   width (ピクセル 内部でメートルに変換)
     * @param   height (ピクセル 内部でメートルに変換)
     * @param   density
     * @param   friction
     * @param   restitution
     * @return
     */
    public function createB2BoxDef(width:int, height:int, 
                    density:Number,
                    friction:Number,
                    restitution:Number):b2PolygonDef {
        
        var boxdef:b2PolygonDef = new b2PolygonDef();
        //B2DBox用単位・中心座標からの距離のサイズに変換して作成
        boxdef.SetAsBox(width / 2 / this.m_b2_physcale,
                height/ 2 / this.m_b2_physcale);
        //密度 0だと動かない 大きいと、ぶつかったとき強い
        boxdef.density = density;     
        //摩擦 大きいと、滑りにくい
        boxdef.friction = friction;   
        //跳ね返り 大きいと、反発しやすい(ゴムっぽくなる)
        //小さいと、粘土っぽくなる
        boxdef.restitution = restitution;  
        
        return boxdef;
    }

    
    /**
     * 円の性質設定(形状と素材)
     * @param   diameter (ピクセル 内部でメートルに変換)
     * @param   height (ピクセル 内部でメートルに変換)
     * @param   density
     * @param   friction
     * @param   restitution
     * @return
     */
    public function createB2CircleDef(diameter:int, 
                    density:Number, 
                    friction:Number, 
                    restitution:Number):b2CircleDef {
        
        var cdef:b2CircleDef = new b2CircleDef();
        //メートル単位・中心座標からの距離のサイズに変換して作成
        cdef.radius = diameter / 2 / this.m_b2_physcale;  //半径
        //密度 0だと動かない
        cdef.density = density;     
        //摩擦 大きいと、滑りにくい
        cdef.friction = friction;   
        //跳ね返り 大きいと、反発しやすい(ゴムっぽくなる)
        //小さいと、粘土っぽくなる
        cdef.restitution = restitution;  
        
        return cdef;
    }
    
    
    /**
     * 配置設定
     * @param   x(ピクセル worldの中心から物体の中心の距離)
     * @param   y(ピクセル)
     * @param   angle 角度 (360度単位)
     * @param   viewdata  表示用Sprite
     * @param   viegroup  表示用Spriteを入れるSprite
     * @return  2BodyDef
     */
    public function createB2BodyDef(x:Number, y:Number, w:Number, h:Number, 
					angle:Number,viewdata:Sprite = null,viewgroup:Sprite = null):b2BodyDef {
        
        var bodydef:b2BodyDef = new b2BodyDef();
        //B2DBox用単位に変換して配置
        bodydef.position.Set(x / this.m_b2_physcale, y / this.m_b2_physcale);
        bodydef.angle = (angle / 180) * Math.PI; //ラジアンに変換
        
        //動かないときはスリープ→止まったらイベント受け付けなくなるので起こす
        bodydef.allowSleep = true;  
        
        if(viewdata != null){
            bodydef.userData = viewdata;            
            bodydef.userData.width = viewdata.width;
            bodydef.userData.height = viewdata.height;
        
            //表示用に追加
            if(viewgroup != null){
                viewgroup.addChild(bodydef.userData);
            }
        }
        
        return bodydef;   
    }

    
    /**
     * 座標指定用のベクトル作成(単位をピクセルからメートルに変換)
     * @param   x
     * @param   y
     * @return  b2Vec2
     */
    public function createB2Vec(x:Number, y:Number):b2Vec2 {
        
        //単位をb2用に変換
        var vec:b2Vec2 = new b2Vec2(x / this.m_b2_physcale,
									y / this.m_b2_physcale); 
        return vec;
    }
    
    /**
     * ベクトル作成
     * @param   vx
     * @param   vy
     * @return  b2Vec2
     */
    public function createB2Axis(vx:Number, vy:Number):b2Vec2 {
        var vec:b2Vec2 = new b2Vec2(vx,vy); 
        return vec;
    }
	
	
	//Joint
	
    /**
     * 距離ジョイントの作成(2つの物体を二つのポイントで結びつける)
     * @param   obj1
	 * @param   obj2
     * @param   anchor1
     * @param  anchor2
     */
	public function makeDistanceJoint(obj1:b2Body,obj2:b2Body,anchor1:b2Vec2,anchor2:b2Vec2):void 
	{
		var jointObj:b2DistanceJointDef = new b2DistanceJointDef();
		jointObj.Initialize(obj1, obj2, anchor1, anchor2);
		this.m_b2_world.CreateJoint(jointObj);
	}
	
    /**
     * 回転ジョイントの作成(2つの物体を二つのポイントで結びつける)
     * @param   obj1
	 * @param   obj2
     * @param   anchor
	 * @param   enableMotor
	 * @param   maxMotorTorque
	 * @param   motorSpeed
	 * @param   enableLimit
	 * @param   lowerAngle
	 * @param   upperAngle
     */
	public function makeRevoluteJoint(obj1:b2Body, obj2:b2Body, anchor:b2Vec2, 
									enableMotor:Boolean = false,
									maxMotorTorque:Number = 0,
									motorSpeed:Number = 0,
									enableLimit:Boolean = false,
									lowerAngle:Number = 0,
									upperAngle:Number = 0):void 
	{
		var jointObjDef:b2RevoluteJointDef = new b2RevoluteJointDef();
		jointObjDef.enableMotor = enableMotor;
		jointObjDef.motorSpeed = maxMotorTorque;
		jointObjDef.maxMotorTorque = motorSpeed;
		jointObjDef.enableLimit = enableLimit;
		
		jointObjDef.lowerAngle = lowerAngle * (Math.PI / 180);
		jointObjDef.upperAngle = upperAngle * (Math.PI / 180);
		
		jointObjDef.Initialize(obj1, obj2, anchor);
		
		this.m_b2_world.CreateJoint(jointObjDef);

	}
	
    /**
     * 直動ジョイントの作成
     * @param   obj1
	 * @param   obj2
     * @param   anchor
	 * @param   enableMotor
	 * @param   maxMotorTorque
	 * @param   motorSpeed
	 * @param   enableLimit
	 * @param   lowerAngle
	 * @param   upperAngle
	 * @return	jointObj
     */
	public function makePrismaticJoint(anchorObj:b2Body, moveObj:b2Body, anchor:b2Vec2, vec:b2Vec2,
									enableMotor:Boolean = true,
									maxMotorForce:Number = 10000,
									motorSpeed:Number = 1,
									enableLimit:Boolean = false,
									lowerTranslation:Number = -100,
									upperTranslation:Number = 100):b2PrismaticJoint
	{
		var jointObj:b2PrismaticJoint;

		var jointObjDef:b2PrismaticJointDef = new  b2PrismaticJointDef();
		jointObjDef.enableMotor = enableMotor;
		jointObjDef.maxMotorForce = maxMotorForce;
		jointObjDef.motorSpeed = motorSpeed;
		jointObjDef.enableLimit = enableLimit;
		jointObjDef.lowerTranslation = lowerTranslation/m_b2_physcale;
		jointObjDef.upperTranslation = upperTranslation / m_b2_physcale;
		jointObjDef.Initialize(anchorObj, moveObj, moveObj.GetPosition(),vec);
		
		jointObj = this.m_b2_world.CreateJoint(jointObjDef) as b2PrismaticJoint;
		
		return jointObj;
	}

	private function startDebugMode():void 
	{
		//DebugDrawを有効にする
		var debugDraw:b2DebugDraw = new b2DebugDraw();
		debugDraw.m_sprite = this;
		debugDraw.m_drawScale = m_b2_physcale;
		debugDraw.m_fillAlpha = .8;
		debugDraw.m_lineThickness = 1;
		debugDraw.m_drawFlags = b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit;
		m_b2_world.SetDebugDraw(debugDraw);
		
	}
	
	
	
	//getter/setter
	public function get world():b2World { return m_b2_world; }
	
	public function set world(value:b2World):void 
	{
		m_b2_world = value;
	}
}