Box2DでActionScript物理プログラミング

第4回 いろいろな形の物体を作る

この記事を読むのに必要な時間:およそ 4 分

三角形を作るには

円の次は三角形に挑戦します。ドラッグアンドドロップで三角形を作れるようにするのは難しいので,クリックした場所に点が打たれ,3つ目の点を打ち終わった時点で三角形が作られるようにします。

このソースをコンパイルすると,以下のようなFlashが生成されます。

点を3つ打つと三角形ができますね。ちなみに点を打つときは時計回りになるようにしてください。反時計回りに点を打つと不自然な動作をします。これはBox2Dの仕様です。ユーザが点を打つなどして三角形を作るようなFlashを作る場合は,何らかの方法で時計回りに限定する必要があります。このサンプルでは三角形を作ることに集中するため,想定外の入力を無視するような処理は省いています。

全体の流れについて

今まではマウスのボタンが押されたときと離されたときのイベントを拾って処理をしていましたが,今回はクリックされたときのイベント(MouseEvent.CLICK)をclickHandlerメソッドで拾って処理します。

stage.addEventListener(MouseEvent.CLICK, clickHandler);

メインとなる処理は,このclickHandlerの中に書きます。1度目のクリックと2度目のクリックでは,クリックされた場所を配列に記憶しておきます。3度目になると,b2PolygonDefを使って三角形の設定を行い,物理エンジン内に配置します。

サンプルを動かしてみると分かりますが,クリックした点には小さい円が描かれます。長方形と円のときはこういった補助的な描画は行いませんでしたが,今回は少し分かりにくいかと思ったのでこの処理を追加しました。円を描く処理はenterFrameHandlerに書いてあります。

クリックされた点を記憶する

三角形を作るためには,点が3つ必要です。この点を記憶しておくために,pointsという配列をDrawingPolygonクラスのプロパティとして用意します。また,次に打とうとしている点が何番目の点なのかを表すpointIndexも用意します。

private var points:Array = [new Point(), new Point(), new Point()];
private var pointIndex:int = 0;

マウスがクリックされてclickHandlerが呼ばれたら,pointsにクリックされた座標を記録していきます。

points[pointIndex].x = event.stageX / DRAW_SCALE;
points[pointIndex].y = event.stageY / DRAW_SCALE;

pointIndex++;
if (pointIndex < points.length) {
	return;
}
pointIndex = 0;

最初にクリックされたはpointIndexが0なので,配列の0番目にクリックされた座標が入ります。その後,pointIndexに1を加えます。pointIndexが必要な点の数より少なければ,return文で処理を終了します。2回目のクリックでも同様に配列の1番目に座標が記録されます。

3回目のクリックになると,if文の条件が3 < 3となり,成り立たなくなります。するとreturn文を通過しないので,if文の先に処理が進みます。そこではまず,pointIndexを0にリセットします。

中心座標を設定する

ここまでpointsに記憶してきた3つの点を使って三角形を作ります。三角形は,長方形のときと同じくb2BodyDefとb2PolygonDefを使って定義します。b2BodyDefには中心座標を設定しなければならないので,それを計算するところからはじめます。

var center:Point = new Point();
var i:int;
for (i = 0; i < points.length; ++i) {
	center.x += points[i].x;
	center.y += points[i].y;
}
center.x /= points.length;
center.y /= points.length;

まず,計算結果を入れるためにcenterという変数を作ります。これに対してクリックした点のX,Y座標を全て足していきます。合計した値を点の数で割って平均を取ると,三角形の中心座標になります。

中心座標が求まったので,b2BodyDefクラスの変数bodyDefを作り,座標を設定します。

var bodyDef:b2BodyDef = new b2BodyDef();
bodyDef.position.Set(center.x, center.y);

頂点などを設定する

次はb2PolygonDefの設定です。長方形のときにも使ったクラスですが,使い方が違います。

var shapeDef:b2PolygonDef = new b2PolygonDef();
shapeDef.vertexCount = points.length;
for (i = 0; i < points.length; ++i) {
	shapeDef.vertices[i].Set(points[i].x - center.x, points[i].y - center.y);
}

違いが分かったでしょうか。長方形のときはSetAsBoxやSetAsOrientedBoxを使って形を設定していましたが,三角形の場合はvertexCountとverticesを使います。

vertexCountには,頂点の数を設定します。三角形なので3を設定すればいいのですが,後々のことを考えてpointsの要素数としておきます。,それぞれの座標についてはverticesという配列に設定しています。verticesはb2Vec2クラスの配列なので,Setメソッドを使って座標を設定します。

verticesに設定する座標は,bodyDef.positionに設定した中心座標からみた相対的な値でなければなりません。そのため,クリックされた座標から中心座標を引いた値を使います。

著者プロフィール

木村秀敬(きむらひでたか)

茨城高専,北陸先端大を卒業後,独立系ベンチャーにあこがれてjig.jpに就職。 ActionScript好きですが,根はコテコテのC/C++プログラマです。Flash/ActionScriptに興味のある方は是非Spark Projectへ。