cocos2d-x で Box2D を使う 〜 衝突判定
はじめに
cocos2d-x と Box2D のテスト引き続き。
物体同士が衝突したときに削除するような処理を追加します。
やること
衝突イベントのリスナークラスを作成し、衝突したら削除フラグをたてる。
物体の削除処理で、画面外に出たものだけでなく、削除フラグが立っているものも削除する。
地面と物体の判定のためのタグをConfigで持つように
- タグ名をイベントリスナーからも参照するので GameScene::kTag を Config::kTag にコピー
- 呼び出しているコードもあわせて変更する
Config.h
class Config { public: enum kTag { kTag_Ground, kTag_Sprite }; };
物体にデリートフラグを追加する
PhysicsSprite.h
protected: bool deleteFlag; public: void setDeleteFlag(bool flag); bool getDeleteFlag();
PhysicsSprite.cpp
void PhysicsSprite::setDeleteFlag(bool flag) { deleteFlag = flag; } bool PhysicsSprite::getDeleteFlag() { return deleteFlag; }
衝突イベントのリスナークラスを作成する
- ヘッダーファイルを追加する
GamePhysicsContactListener.h
#ifndef b2test_GamePhysicsContactListener_h #define b2test_GamePhysicsContactListener_h #include <math.h> #include "cocos2d.h" #include "Box2D.h" #include "PhysicsSprite.h" #include "Config.h" USING_NS_CC; class GamePhysicsContactListener : public b2ContactListener { public: // 衝突時の処理 void BeginContact(b2Contact* contact) { // 衝突した双方の物体を取得 b2Body* bodyA = contact->GetFixtureA()->GetBody(); b2Body* bodyB = contact->GetFixtureB()->GetBody(); // 物体にひもづくSpriteを取得 PhysicsSprite* spriteA = (PhysicsSprite*)bodyA->GetUserData(); PhysicsSprite* spriteB = (PhysicsSprite*)bodyB->GetUserData(); // 地面との衝突は無視する if (spriteA->getTag() == Config::kTag_Ground || spriteB->getTag() == Config::kTag_Ground) { return; } // 衝突時の加速度を取得 b2Vec2 velocityA = bodyA->GetLinearVelocity(); b2Vec2 velocityB = bodyB->GetLinearVelocity(); CCLOG("[BeginContact] A(%f, %f) B(%f, %f)", velocityA.x, velocityA.y, velocityB.x, velocityB.y); // 加速度が一定上の大きさだったら、ぶつかられた方を削除する float threshold = 3; if (pow(velocityA.x, 2) + pow(velocityA.y, 2) > pow(threshold, 2)) { spriteB->setDeleteFlag(true); } if (pow(velocityB.x, 2) + pow(velocityB.y, 2) > pow(threshold, 2)) { spriteA->setDeleteFlag(true); } } }; #endif
イベントリスナーを登録する
GameScene.cpp
- initPhysics() の末尾に追記する
// 衝突判定の初期化 GamePhysicsContactListener* contactListener = new GamePhysicsContactListener(); world->SetContactListener(contactListener);
削除フラグが立ってたら物体を削除
GameScene.cpp
- deleteSprite() の削除判定に削除フラグを追加
// 画面外に出たか、削除フラグが立っていたら、削除 if (x < 0 || size.width < x || y < 0 || size.height < y || pSprite->getDeleteFlag()) {