物理エンジンライブラリ Box2DFlashAS3(基本)
Box2DFlashAS3に再チャレンジです。バージョンは2.0.2を使用
使い方等ざっと自分用にまとめ。
使い方
- 領域(b2AABB)・重力(b2Vec2)・スリープ(Boolean)設定して、Box2Dの世界(b2World)作成
- 性質(b2ShapeDef)設定(素材(密度・摩擦力・反発力)、形状(多角形・円、サイズ))
- 配置(b2BodyDef)設定(配置座標、配置角度、表示用オブジェクト、スリープ指定)
- B2世界上で、配置から物体(b2Body)作成。物体上で性質から形状(b2Shape)作成。形状を固める。
- 一定時間毎(EnterFrameイベントなど)で演算させ、結果を表示用オブジェクトに反映させる
Box2Dの単位
- Box2Dの単位はメートル。縦横1を指定した箱を作ると、縦横1メートルの箱を作ることになる。
- Box2Dの指定・算出したサイズや座標の値をそのまま使うと、1ピクセル1メートルの世界になってしまう。でかい。
- なので、スケールを指定してやって、100ピクセル1メートルとかにして使用する。
Box2Dの基点(原点)
- Box2Dの基点は中心。
- サイズ指定するときは、中心からの距離で指定する。
- 長方形なら、辺の半分、円なら半径を指定、多角形は中心座標を指定して、そこから頂点の距離
- 座標の指定も、左上ではなく、中心を指定。Flashでパーツを作る場合は、ステージの中心を原点にする。
サンプルコード
ベースのクラス(Box2Dの機能を適当にまとめたもの)
Actionscript:
-
public class B2Base extends Sprite
-
{
-
//Box2Dのバージョンは2.0.2
-
-
protected var m_b2_world:b2World;
-
//縮尺 1mを何ピクセルで表すか
-
protected var m_b2_physcale:Number = 10;
-
//演算制度 大きいと正確だけど、負荷が大きい
-
protected var m_b2_iterations:int = 10;
-
// 演算をfpsに合わせる
-
protected var m_b2_timeStep:Number = 24.0;
-
-
//constructor
-
public function B2Base(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);
-
}
-
-
//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, 10.0);
-
-
// 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
-
*/
-
protected 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, 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 diameter 直径(ピクセル 内部でメートルに変換)
-
* @param x (ピクセル 内部でメートルに変換)
-
* @param y(ピクセル 内部でメートルに変換)
-
* @param density 密度 0にすると固定 大きいと、ぶつかったとき強い
-
* @param friction 摩擦 大きいと滑りにくい
-
* @param restitution 跳ね返り 大きいと、反発しやすい
-
* @param viewdata 表示用のSprite
-
* @param viewgroup 表示用のSpriteを入れるSprite
-
* @return b2Body
-
*/
-
protected 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,
-
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
-
*/
-
private 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
-
*/
-
private function createB2CircleDef(diameter:int,
-
density:Number,
-
friction:Number,
-
restitution:Number):b2CircleDef {
-
-
var cdef:b2CircleDef = new b2CircleDef();
-
//メートル単位・中心座標からの距離のサイズに変換して作成
-
cdef.radius = radius / 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
-
*/
-
private function createB2BodyDef(x:Number, y: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
-
*/
-
protected 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;
-
}
-
-
}
ベースを使っていろいろやるクラス
Actionscript:
-
public class StudyB2Base extends B2Base
-
{
-
-
private var m_kinokoL:Sprite;
-
private var m_kinokoS:Sprite;
-
-
public function StudyB2Base() :void {
-
-
super(24, 10, 10);
-
-
this.initOka(); //丘
-
this.initKinokoL(); //大きいきのこ
-
this.initKinokoS(); //小さいきのこ
-
-
this.addEventListener(Event.ENTER_FRAME, update, false, 0, true);
-
-
//this.setDebugDraw();
-
}
-
-
-
//丘と地面作る(固定)
-
private function initOka():void {
-
-
//固定なのでUserDataは入れない
-
-
//丘
-
this.makeB2BodyBox(80, 200, 140, 380, 0, 0, 0.5, 0.5);
-
this.makeB2BodyBox(80, 40, 220, 260, 0, 0, 0.5, 0.5);
-
this.makeB2BodyBox(80, 40, 300, 220, 0, 0, 0.5, 0.5);
-
-
this.makeB2BodyBox(40, 40, 360, 260, 0, 0, 0.5, 0.5);
-
this.makeB2BodyBox(40, 40, 400, 300, 0, 0, 0.5, 0.5);
-
this.makeB2BodyBox(40, 40, 440, 340, 0, 0, 0.5, 0.5);
-
this.makeB2BodyBox(40, 120, 480, 420, 0, 0, 0.5, 0.5);
-
-
//地面
-
this.makeB2BodyBox(600, 20, 300, 490, 0, 0, 0.5, 0.5);
-
}
-
-
-
//丘の上に生えてる大きいきのこ作る
-
private function initKinokoL():void {
-
-
var self:StudyB2Base = this;
-
-
//これはMC配置するだけ
-
var kinoko:MovieClip = new kinoko_L_MC;
-
kinoko.x = 300;
-
kinoko.y = 125;
-
-
kinoko.buttonMode = true;
-
-
kinoko.addEventListener(MouseEvent.MOUSE_OVER,
-
function(e:Event):void {
-
kinoko.gotoAndPlay("frm_hover");
-
});
-
-
kinoko.addEventListener(MouseEvent.MOUSE_UP,
-
function(e:Event):void {
-
kinoko.gotoAndPlay("frm_action");
-
self.makeKinokoS(Math.random() * 100 + 250, 0);
-
});
-
-
this.m_kinokoL = kinoko;
-
-
this.addChild(this.m_kinokoL);
-
-
}
-
-
-
//小さいきのこ入れるのを作って、小さいきのこ配置
-
private function initKinokoS():void {
-
-
//小さいきのこを入れる
-
this.m_kinokoS = new Sprite();
-
this.addChild(this.m_kinokoS);
-
-
//最初の小さいきのこ配置
-
this.makeKinokoS(120, 0);
-
this.makeKinokoS(160, 0);
-
this.makeKinokoS(200, 0);
-
this.makeKinokoS(240, 0);
-
this.makeKinokoS(360, 0);
-
this.makeKinokoS(400, 0);
-
this.makeKinokoS(440, 0);
-
this.makeKinokoS(480, 0);
-
}
-
-
-
//小さいきのこ作成
-
private function makeKinokoS(x:Number, y:Number):void {
-
-
var kinoko:Sprite;
-
var land = Math.random();
-
-
if (land>= 0.6) {
-
//普通のきのこ
-
kinoko = new kinoko_S1_MC as Sprite;
-
}
-
else if(land>= 0.3){
-
//怪しいきのこ
-
kinoko = new kinoko_S2_MC as Sprite;
-
}
-
else {
-
//しめじ
-
kinoko = new kinoko_S3_MC as Sprite;
-
}
-
-
this.makeB2BodyCircle(30, x, y, 1.0, 0.5, 0.5,
-
kinoko, this.m_kinokoS);
-
}
-
-
-
//演算
-
private function update(e:Event):void{
-
-
//B2Boxの時間進める
-
this.m_b2_world.Step(this.m_b2_timeStep, this.m_b2_iterations);
-
-
//各B2BoxのBodyの動きにあわせて中のSpriteを動かす
-
for (var bb:b2Body = this.m_b2_world.m_bodyList; bb; bb = bb.m_next){
-
-
var bb_x:Number = bb.GetPosition().x * m_b2_physcale;
-
var bb_y:Number = bb.GetPosition().y * m_b2_physcale;
-
-
//画面外に出て行ったきのこ削除
-
if (bb_x <-50 || bb_x> 650 || bb_y <-50 || bb_y> 550) {
-
this.m_b2_world.DestroyBody(bb);
-
if(bb.m_userData != null){
-
this.m_kinokoS.removeChild(bb.m_userData);
-
bb.m_userData = null;
-
}
-
}
-
-
//演算結果にあわせて表示用データ移動
-
if (bb.m_userData is Sprite){
-
//メートルからピクセル単位に変換
-
bb.m_userData.x = bb_x;
-
bb.m_userData.y = bb_y;
-
bb.m_userData.rotation = bb.GetAngle() * (180/Math.PI);
-
}
-
}
-
}
-
-
}



冷吟閑酔 2009-06-18 06:11:47 (ピンバック)
[...] 物理エンジンライブラリ Box2DFlashAS3(基本) http://hokori.net/2009/02/18/box2dflashas3_base/ [...]
Box2DFlashAS3: 物理演算シミュレーションを可能にするActionScriptライブラリ | DigiTechLog Dot Com 2010-01-28 12:15:16 (ピンバック)
[...] 物理エンジンライブラリ Box2DFlashAS3(基本) [...]