Box2DFlashAS3での衝突判定

Box2D LetterFIC

昨日に引き継ぎBox2DFlashAS3、楽しすぎます。
FICC安藤です。

今回は、もしゲームを作るとなると必要になると思われる「当たり判定」です。
上のサンプルでは3つのルールがあって

1 敵役は星形
2 マウスクリックで左側から玉が飛んでくる
3 玉が敵に当たるとエフェクトを残して玉だけ消す。

今まではMovieClip.hitTest() で毎フレームごとにぶつかってるのがいないか走査してたと思います。
Box2Dではworld内の物は特別なにもしなくてもお互いがぶつかれば反発しあって跳ね返ります。
まぁそういうエンジンですからと言えばそれまでですが、逆にただレンダリングしてるだけだと「いつ何が何とぶつかったか?」がわかりません。

ぶつかった時のイベント等ないかソースを見てみましたがそれっぽいものは見当たらず、
Box2D/Dynamics/Contacts/b2ContactNode が怪しかったのでそれを使います。

このb2ContactNodeでわかるのは「何と何がぶつかったか」のリストで、これはb2Body内のm_contactListに収まっています。

実際のコードで見てみます。

TestBed/Testでのサンプルでは描画ループはこんな感じになってます。

for (var bb:b2Body = m_world.m_bodyList; bb; bb = bb.m_next){
	for (var s:b2Shape = bb.GetShapeList(); s != null; s = s.GetNext()){
		drawShape(s);
	}
}


ここにb2ContactNodeを取得するコードを追加

for (var bb:b2Body = m_world.m_bodyList; bb; bb = bb.m_next){
	//	ここから
	//	追記:もしかしたら↑のループの外でb2Contactを使っても可能なのかも(未確認)
	for (var cn:b2ContactNode = bb.m_contactList; cn != null; cn = cn.next){
		trace(cn.contact.GetShape1().m_body);
		trace(cn.contact.GetShape2().m_body);
	}
	//	ここまで
	for (var s:b2Shape = bb.GetShapeList(); s != null; s = s.GetNext()){
		drawShape(s);
	} 			
}

これで衝突している2つのb2Bodyが取得できるので、玉だけを消す事が出来ます。

実際には敵b2Bodyには userData.id = 'enemy'、玉b2Bodyには userData.id = 'bullet' を追加して
1つの玉が2つの敵に同時に当たる可能性もあるのですでに消されてないかをチェックしてから削除しています。

for (var cn:b2ContactNode = bb.m_contactList; cn != null; cn = cn.next){
	var body1:b2Body;
	var body2:b2Body;
	var bulletEffect:BulletEffect;	
	if(cn.contact.GetShape1() && cn.contact.GetShape2()){
		body1 = cn.contact.GetShape1().m_body;
		body2 = cn.contact.GetShape2().m_body;
	if(body1.m_userData.id == 'bullet' && body2.m_userData.id == 'enemy'){
			m_world.DestroyBody(body1);
			bulletEffect = new BulletEffect();
			bulletEffect.x = body1.m_position.x;
			bulletEffect.y = body1.m_position.y;
			Main.effectContainer.addChild(bulletEffect);
	
		}
	if(body1.m_userData.id == 'enemy' && body2.m_userData.id == 'bullet'){
			m_world.DestroyBody(body2);
			bulletEffect = new BulletEffect();
			bulletEffect.x = body2.m_position.x;
			bulletEffect.y = body2.m_position.y;
			Main.effectContainer.addChild(bulletEffect);
		}	
	}
}

ちなみに、その玉が左から飛んでくる部分は Box2D/Common/Math/b2Vec2 を使います。

var body:b2BodyDef = new b2BodyDef();
body.linearVelocity = new b2Vec2(1000, 0);
//	b2Vec2(x軸の移動量, y軸の移動量)

これで一部変な挙動(星の下の方だとあんまり反応薄かったり)は残りますが、物理エンジンシューティングとか作ってみたり、とか、どうでしょう?

以下今回のソースファイルです。
Source:box2d_shotthestar.zip

*パブリッシュにはBox2D以外にサンプルに含まれたGeneral/FRateLimiter.as, General/Input.as が必要です。

トラックバック(0)

このブログ記事を参照しているブログ一覧: Box2DFlashAS3での衝突判定

このブログ記事に対するトラックバックURL: http://www.ficc.jp/cgi-bin/mt4/mt-tb.cgi/16

コメントする