2009.9.28
Box2D(Box2DFlashAS3)によるActionScript物理シミュレーション

●第5回:様々な形状の物体を作る

◆へこんだ図形の作成

へこんだ図形は、複数のb2ShapeDefオブジェクトを作成しそれぞれをb2Body.CreateShape()メソッドでb2Bodyオブジェクトの子として適用することで作れます。
この場合の注意点としては、b2BodyDef.positionプロパティによる座標位置とb2PolygonDef.verticesプロパティの頂点の座標位置は相対的に維持される、ということです。
つまり、5角形のサンプルのようにb2BodyDef.positionプロパティの座標とb2PolygonDef.verticesプロパティの頂点座標が離れたところにあると、「基準点が離れたところにあるムービークリップ」のようになってしまいます。そうなると、物体を制御する際に分かりにくくなるのであまりよくありません。
今回は三角形を2つくっつけてやじり型を作ってみようと思いますが、b2BodyDef.positionプロパティを(x = 0, y = 0)に設定し、複数のb2ShapeDefオブジェクトの頂点座標の位置も(x = 0, y = 0)を基準とした位置で指定します。
物体は当然(x = 0, y = 0)に作成され、画面上左上に配置されます。それをb2Body.SetXForm()メソッドで移動させようと思います。
b2Body.SetXForm()メソッドは物体の位置と回転角度を変更できます。

【M】b2Body.SetXForm(position:b2Vec2, angle:Number) : Boolean-b2Bodyオブジェクトの位置と回転角度を設定する。

引数-position:b2Bodyオブジェクトの新たな座標位置を表すb2Vec2オブジェクト/angle:回転角度(ラジアン)を表す数値。
戻り値-移動先が物理ワールド外だった場合にはfalseを返し、凍結状態となる。

以下、スクリプトコードです。やはり動体の生成のセクションが主な相違点です。
3角形のb2PolygonDefオブジェクトを2つ作成し、それらをb2Bodyオブジェクトの子として適用している部分を青の太字で表示しておきます。

スクリプト:5-4

//Box2D_05_03.as
package {
    //▼インポート
    import flash.display.Sprite;
    import Box2D.Collision.b2AABB;
    import Box2D.Common.Math.b2Vec2;
    import Box2D.Dynamics.b2World;
    import Box2D.Dynamics.b2BodyDef;
    import Box2D.Collision.Shapes.b2PolygonDef;
    import Box2D.Dynamics.b2Body;
    import Box2D.Dynamics.b2DebugDraw;
    import flash.events.Event;

    public class Box2D_05_03 extends Sprite {
        //▼定数定義
        //1mを表すピクセル数

        private static const DRAW_SCALE:Number = 100;
        //▼プロパティ定義
        private var _world:b2World;
        private var _bArrow:b2Body;
        //▼コンストラクタ定義
        public function Box2D_05_03() {
            //▼物理エンジンのセットアップ
            //物理エンジン適用範囲の設定(ステージの100ピクセル外側)

            var worldRegion:b2AABB = new b2AABB();//矩形作成
            worldRegion.lowerBound.Set(-1, -1);
            worldRegion.upperBound.Set(6.5, 5);
            //重力の設定
            var gravity:b2Vec2 = new b2Vec2(0, 9.8);
            //範囲・重力・スリープの有無を指定して物理ワールドを作成
            _world = new b2World(worldRegion, gravity, true);

            //▼床(静体)の生成
            //BodyDefの設定

            var bdFloor:b2BodyDef = new b2BodyDef();
            bdFloor.position.Set(5.5 / 2, 3);
            //ShapeDefの設定
            var pdFloor:b2PolygonDef = new b2PolygonDef();
            pdFloor.SetAsBox(2, 0.15);
            //ボディの生成
            var bFloor:b2Body = _world.CreateBody(bdFloor);
            bFloor.CreateShape(pdFloor);

            //▼やじり型(動体)の生成
            var bdArrow:b2BodyDef = new b2BodyDef();
            bdArrow.position.Set(0, 0);
            //1つめのb2ShapeDefオブジェクトを生成
            var shape1:b2PolygonDef = new b2PolygonDef();
            shape1.vertexCount = 3;
            shape1.vertices[0].Set(0, -0.25);
            shape1.vertices[1].Set(0,0);
            shape1.vertices[2].Set(-0.25, 0.25);
            shape1.density = 1;
            shape1.restitution = 0.5;
            //2つめのb2ShapeDefオブジェクトを生成
            var shape2:b2PolygonDef = new b2PolygonDef();
            shape2.vertexCount = 3;
            shape2.vertices[0].Set(0, -0.25);
            shape2.vertices[1].Set(0.25, 0.25);
            shape2.vertices[2].Set(0, 0);
            shape1.density = 1;
            shape2.restitution = 0.5;
            //ボディの生成
            _bArrow = _world.CreateBody(bdArrow);
            _bArrow.CreateShape(shape1);
            _bArrow.CreateShape(shape2);
            //位置の設定
            _bArrow.SetXForm(new b2Vec2(5.5 / 2, 1), 0);
            //質量の設定
            _bArrow.SetMassFromShapes();

            //▼描画設定
            var dd:b2DebugDraw = new b2DebugDraw();
            dd.m_sprite = this;
            dd.m_drawScale = DRAW_SCALE; //1mを100ピクセルにする
            dd.m_fillAlpha = 0.3; //塗りのアルファ値
            dd.SetFlags(b2DebugDraw.e_shapeBit);//物体を表示する設定に
            _world.SetDebugDraw(dd);//物理ワールドにセット

            //▼イベントリスナーの追加
            addEventListener(Event.ENTER_FRAME, _enterFrameHandler);
        }

        //▼イベントリスナー定義
        private function _enterFrameHandler(eventObj:Event):void {
            _world.Step(1 / 24, 10);//物理シミュレーションの更新
        }
    }
}

落下するやじり型

↑グラフィックイメージをクリックすると、swfファイルが別ウィンドウで開きます。

さて、これでやじりのようなへこんだ形も作成できました。
→サンプルファイル【Box2D_05_03.zip
ところで…b2ShapeDefオブジェクトとして作成した2つの三角形はx軸を中心に左右対称にしたつもりです。
しかし、動作を見るとはずんで左にずれるのが分かります↓。

バウンドして左に倒れるやじり型

これは「重心」が関係しています。物体には基準点のほかに重心の概念があります。
次回は、重心に関する話や物体の制御に関する内容を扱おうと思います。もしかしたら何回かに分けて扱うかもしれません。
今回もb2Body.SetXForm()メソッドで位置を変更してみましたが、Box2Dには他にも様々な面白いメソッドがあります。次回の更新までは少々時間をいただくかもしれませんがお楽しみに。

このサイトへのご意見・ご感想は[takuya@haphands.com]までお願いします!