◆円の作成
前回まではb2PolygonDefクラスでSetAsBox()メソッドを使って長方形を作ってきました。
今回は長方形以外の形を作ってみようと思います。最初は円を作ります。
第3回で述べたように、形状はb2ShapeDefクラスのサブクラスであるb2PolygonDefクラスかb2CircleDefクラスで指定します。
円はb2CircleDefオブジェクトを生成し、b2CircleDef.radiusプロパティで半径を指定します。
【コンストラクタ】b2CircleDef()-b2CircleDefオブジェクトの生成
【P】b2CircleDef.radius:Number-半径(m)を表す数値
前回の【スクリプト:4-5】(Box2D_04_02.as)とほぼ同じ手順です。
変数名が変わったりもしていますが、「▼箱(動体)の生成」のセクションが「▼ボール(動体)の生成」セクションになっているのが大きな変更点です。これにより動体の形状を長方形から円にします。今回は重要部分を青の太字で表示します。
スクリプト:5-1 |
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;
import Box2D.Collision.Shapes.b2CircleDef;
public class Box2D_05_01 extends Sprite {
private static const DRAW_SCALE:Number = 100;
private var _world:b2World;
private var _bBall:b2Body;
public function Box2D_05_01() {
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);
var bdFloor:b2BodyDef = new b2BodyDef();
bdFloor.position.Set(5.5 / 2, 3);
var pdFloor:b2PolygonDef = new b2PolygonDef();
pdFloor.SetAsBox(2, 0.15);
var bFloor:b2Body = _world.CreateBody(bdFloor);
bFloor.CreateShape(pdFloor);
var bdBall:b2BodyDef = new b2BodyDef();
bdBall.position.Set(5.5 / 2, 1);
var pdBall:b2CircleDef = new b2CircleDef();
pdBall.radius = 0.25;
pdBall.density = 1;
pdBall.restitution = 0.5;
_bBall = _world.CreateBody(bdBall);
_bBall.CreateShape(pdBall);
_bBall.SetMassFromShapes();
var dd:b2DebugDraw = new b2DebugDraw();
dd.m_sprite = this;
dd.m_drawScale = DRAW_SCALE;
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ファイルが別ウィンドウで開きます。
b2DebugDrawによる円は、中心から半径分の直線が1本追加されたものとして描画されます。
これにより、円が回転した場合にその状況が確認しやすくなります(今回は回転しませんが)。
→サンプルファイル【Box2D_05_01.zip】
◆多角形の作成
多角形は長方形と同様にb2PolygonDefクラスを使って定義します。が、定義方法は全く異なります。
多角形はb2PolygonDef.vertexCountプロパティによる頂点の数の指定と、b2PolygonDef.verticesプロパティによる頂点座標の指定が必要になります。b2PolygonDef.verticesプロパティはb2Vec2オブジェクトを要素とするArrayオブジェクトで、デフォルトで(x = 0, y = 0)のb2Vec2オブジェクトが8つ設定されています。
【P】b2PolygonDef.vertexCount:int-多角形の頂点数を表す整数値
【P】b2PolygonDef.vertices:Array-頂点の座標を表すb2Vec2オブジェクトを要素とするArrayオブジェクト
頂点座標を指定する場合、次の2つの注意点があります。
1つめの、時計回りに指定するというのはBox2Dのマニュアルで指定されています。
ちなみにマニュアルでは「右手座標系に基づいて反時計回りに指定」と記載されています。右手座標系とは、X軸を右向き、Y軸を上向き、Z軸を手前向きに考えた座標系(のよう)です。これをFlashの座標系に置き換えて、反時計回りに指定すると、結果的にFlashの座標系では時計回りの指定になります。
2つめのへこんだ形状というのは、やじりのように3角形の底辺がへこんだ形状や星型などが代表的なものでしょう。
へこんだ図形の例
このような形状を持った物体を作成する場合には、複数の適正なb2ShapeDefオブジェクトを子として持ったb2Bodyオブジェクトを作成します。このような物体の作成も後でやってみようと思います。
まずは、5角形を作成します。
大まかな流れは今までと変わりません。やはり重要部分を青の太字で表示しておきます。
スクリプト:5-2 |
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_02 extends Sprite {
private static const DRAW_SCALE:Number = 100;
private var _world:b2World;
private var _bPentagon:b2Body;
public function Box2D_05_02() {
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);
var bdFloor:b2BodyDef = new b2BodyDef();
bdFloor.position.Set(5.5 / 2, 3);
var pdFloor:b2PolygonDef = new b2PolygonDef();
pdFloor.SetAsBox(2, 0.15);
var bFloor:b2Body = _world.CreateBody(bdFloor);
bFloor.CreateShape(pdFloor);
var bdPentagon:b2BodyDef = new b2BodyDef();
bdPentagon.position.Set(5.5 / 2, 1);
var pdPentagon:b2PolygonDef = new b2PolygonDef();
pdPentagon.vertexCount = 5;
pdPentagon.vertices[0].Set(0, -0.3);
pdPentagon.vertices[1].Set(0.24, -0.1);
pdPentagon.vertices[2].Set(0.16, 0.2);
pdPentagon.vertices[3].Set(-0.16, 0.2);
pdPentagon.vertices[4].Set(-0.24, -0.1);
pdPentagon.density = 1;
pdPentagon.restitution = 0.5;
_bPentagon = _world.CreateBody(bdPentagon);
_bPentagon.CreateShape(pdPentagon);
_bPentagon.SetMassFromShapes();
var dd:b2DebugDraw = new b2DebugDraw();
dd.m_sprite = this;
dd.m_drawScale = DRAW_SCALE;
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ファイルが別ウィンドウで開きます。
5角形なのでb2PolygonDef.vertexCountプロパティに5を設定し、b2PolygonDef.verticesプロパティのインデックス0から4にb2Vec2.Set()メソッドで頂点座標を指定しています。
この方式による形状の指定で特徴的なのは、頂点座標とb2BodyDef.positionプロパティによる物体の位置の関係です。このサンプルでは、5角形の頂点の座標位置は分かりやすさを優先して(x = 0, y = 0)を中心に指定していますが、表示位置はb2BodyDef.positionプロパティで指定した位置になっています。
つまり、頂点の座標位置の指定は絶対的な座標位置が重要なのではなく、形状を表す相対的な位置関係のみが重要と考えてよさそうです。
→サンプルファイル【Box2D_05_02.zip】
・8角形以上の多角形の作成
【スクリプト:5-2】では頂点の座標をb2PolygonDef.verticesプロパティに指定する際に、b2Vec2.Set()メソッドを使いました。これは先に述べた通り、b2PolygonDef.verticesプロパティがデフォルトでb2Vec2オブジェクトを8つ持っているために、8角形までの座標の指定はb2Vec2.Set()メソッドを使うことができるからです。
9個以上の以上の頂点を持った図形を作る場合は自分でb2PolygonDef.verticesプロパティにb2Vec2オブジェクトを追加すればよさそうです。
以下、10角形の動体を作成してみます。頂点座標はforループで取得します。
スクリプトは【スクリプト:5-2】からの変更点のみ挙げておきます。
スクリプト:5-3 |
・インポートのセクションに追加 |
import flash.geom.Point; |
・コンストラクタ内、5角形(動体)の生成セクションの頂点の数と頂点座標の指定部分を書き換え |
pdPentagon.vertexCount = 10;
for (var i:uint = 0; i < pdPentagon.vertexCount; i++){
var pnt:Point = Point.polar(0.25, i * Math.PI / pdPentagon.vertexCount * 2);
pdPentagon.vertices[i] = new b2Vec2(pnt.x, pnt.y);
} |
5角形ではないのに変数名に「Pentagon」のフレーズが入っているのがアレですが、気にしないでおきましょう。
↑グラフィックイメージをクリックすると、swfファイルが別ウィンドウで開きます。
b2PolygonDef.verticesプロパティの値を変更すれば、多角形の形を変更できます。
→サンプルファイル【Box2D_05_02a.zip】