Box2Dの様々な機能について説明してきましたが、
コンタクトリスナを使うと、
サンプルについて
まずはサンプルのFlashをご覧ください。円を作るときのFlashに似ていますが、
動作についての説明
このFlashでは、
コンタクトリスナでは衝突の強さを検出できるので、
全ての物体同士の衝突を見ているので、
サンプルファイルの構成
このFlashを作るためのプログラムと画像は以下のとおりです。本当はこれらのファイルだけではコンパイルできず、
今回のサンプルコードは、
メインのクラスが書かれているのはKiraKira.
コンタクトリスナを使うときには、
star.
tweenerを使うには
もう1点、
コンタクトリスナの仕組み
サンプルプログラムの説明をする前に、
衝突を検出……というと、
メソッドをオーバーライドして衝突を検出する
Box2Dで衝突を検出するには、
public class ContactListener extends b2ContactListener {
public override function Add(point:b2ContactPoint):void {
// 衝突検出時の処理
}
}
このクラスの変数を作り、
var contactListener:ContactListener = new ContactListener();
world.SetListener(contactListener);
その他のオーバーライドできるメソッド
b2ContactListenerクラスには、
- Add
- 物体が衝突したときに呼び出されるメソッド
- Persist
- 物体が衝突してから離れるまで繰り返し呼び出されるメソッド
- Remove
- 物体が離れたときに呼び出されるメソッド

b2ContactPointについて
上で説明した3つのメソッドは、
プロパティは数が多いので、
- position
- 物体が接触している点の座標。サンプルではこの場所から星を飛ばしています
- normalForce
- 衝突の強さ。サンプルではこれに応じて星の数を決めています
- shape1、
shape2 - 接触している物体
(b2Shape型の変数)。これを参照すれば衝突した物体に応じて動作を変えることができます
ContactListenerクラスでの処理
クラスの全体像
では実際にサンプルプログラムがどのように書かれているかを説明します。まずはb2ContactListenerクラスを継承したContactListenerクラスからです。クラスの大まかな形は以下のようになっています。
public class ContactListener extends b2ContactListener {
public var parent:KiraKira;
public function StarContactListener() {
}
// 新しく衝突が発生したときに呼び出されるメソッド
public override function Add(point:b2ContactPoint):void { ... }
}
メインとなるKiraKiraクラスを参照するために、
物体が衝突した時の処理
物体が衝突したときの処理を書くAddメソッドは、
public override function Add(point:b2ContactPoint):void {
// 衝突時の力の大きさをもとに、エフェクトを発生させる数を計算する
var num:int = point.normalForce / 10 + 1;
// 計算ミスで大きな力がかかることがあるので、値を10までに制限する
if (num > 10) {
num = 10;
}
for (var i:int = 0; i < num; ++i) {
parent.addContactEffect(point);
}
}
衝突時の力をもとに、
割り算の結果に1を加えているのは、
numが計算できたら、
星を飛ばすには
説明の舞台をContactListener.
// 物と物が接触したときのエフェクトを発生させる
public function addContactEffect(point:b2ContactPoint):void { ... }
星の画像を読み込む
ではメソッドの中身について説明します。まずは星の画像からSpriteを作ります。ここは前回DebugDrawを使わずに物体を描画したときのパターンと似ているので、
// 星の画像を読み込んで、サイズと位置を調整する
var starImage:Bitmap = new StarImage();
starImage.width = 50;
starImage.height = 50;
starImage.x = -starImage.width / 2;
starImage.y = -starImage.height / 2;
// 星の画像を表示するためのSpriteを作る
// 座標はコンタクトが発生した場所とする
var sprite:Sprite = new Sprite();
sprite.x = point.position.x * DRAW_SCALE;
sprite.y = point.position.y * DRAW_SCALE;
sprite.addChild(starImage);
addChild(sprite);
この処理の結果、
星を飛ばす先の座標を計算する
星を飛ばすときの原点はpoint.
// 星が飛んでいく方向と距離をランダムに決める
// 角度は0~360度、距離は50~150
var angle:Number = Math.random() * 360;
var length:Number = Math.random() * 100 + 50;
方向と距離が決まったら、
// 星が飛んでいく先の座標を計算する
var dx:Number = sprite.x + length * Math.cos(angle);
var dy:Number = sprite.y + length * Math.sin(angle);
tweenerを使って星を飛ばす
座標が求まったのでいよいよ星を飛ばします。setTimeoutを使うなどして星を飛ばすプログラムを自前で書いていくと長くなってしまい、
// Tweenerで星を飛ばす
Tweener.addTween(sprite, {
time: 3, // 3秒間
scaleX: 0, // 消えるまで縮小する
scaleY: 0,
alpha: 0, // 完全に透明にする
rotation: 200, // 少し回転させる
x: dx,
y: dy,
onComplete: function():void {
removeChild(sprite);
}
});
単純に星を飛ばす
3秒経過してアニメーションが終わるとonCompleteが呼び出され、
KiraKiraクラスでは、
まとめ
コンタクトリスナを使い、
コンタクトリスナの挙動が若干おかしい場合もありますが、
7回の連載を通じてBox2Dの解説をしてきましたが、
ライブラリの全ての部分を説明することはできませんでしたが、