Box2D and Collisions
物体が衝突したときにイベントリスナー的なメソッドを呼び出させる仕組みがあるみたい。
今日はそこを試してみようと思います。
std::vector と b2ContactListenerを継承したクラス の扱い方…
やべーこういう実装…経験した事がないww ^^; …とりあえず写経www ^^;;;
まずは b2ContactListener を継承するクラスを追加(MyContactListener) と、std::vector に格納するための 構造体 MyContact を準備します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | //MyContactListener.h #include "cocos2d.h" #include "Box2d.h" #include <vector> #include <algorithm> #pragma mark - struct MyContact { b2Fixture * fixtureA; b2Fixture * fixtureB; bool operator == ( const MyContact & other) const { bool result = (fixtureA == other.fixtureA) && (fixtureB == other.fixtureB); return result; } }; #pragma mark - class MyContactListener : public b2ContactListener { public : MyContactListener(); virtual ~MyContactListener(); public : std::vector<MyContact>_contacts; #pragma mark - ### b2ContactListener オーバーライド ### public : virtual void BeginContact(b2Contact* contact); virtual void EndContact(b2Contact* contact); virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold); virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse); }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #include "MyContactListener.h" #pragma mark - MyContactListener::MyContactListener() : _contacts() { } MyContactListener::~MyContactListener() { } #pragma mark - void MyContactListener::BeginContact(b2Contact *contact) { MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB() }; _contacts.push_back(myContact); } void MyContactListener::EndContact(b2Contact *contact) { MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB() }; std::vector<MyContact>::iterator pos; pos = std::find(_contacts.begin(), _contacts.end(), myContact); if (pos != _contacts.end()) { _contacts.erase(pos); } } void MyContactListener::PreSolve(b2Contact *contact, const b2Manifold *oldManifold) { } void MyContactListener::PostSolve(b2Contact *contact, const b2ContactImpulse *impulse) { } |
…うーんw とりあえず雰囲気をつかむかww ^^;;;
下準備ができたので、 HelloWorld で、まず変数定義してクラス変数を準備ですね。
1 2 3 4 5 6 7 8 9 10 11 | //HelloWorldScene.h #include "MyContactListener.h" class HelloWorld : public cocos2d::CCLayer { //...(省略) protected : MyContactListener * _contactListener; //...(省略) }; |
aaa
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | //HelloWorldScene.cpp HelloWorld::HelloWorld() { //...(省略) _contactListener = NULL; } HelloWorld::~HelloWorld() { //...(省略) CC_SAFE_DELETE(_contactListener); _contactListener = NULL; } bool HelloWorld::init() { bool result = false ; do { const CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); //const CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin(); const CCPoint center = ccpMult(ccpFromSize(visibleSize), 0.5f); this ->initPhysics(); //Create Contact Listener { _contactListener = new MyContactListener(); //今回のポイント _world->SetContactListener(_contactListener); } //...(省略) result = true ; } whild(0); return result; } |
これで準備はOKみたい。床とボールの衝突判定の実装は updateに記述。
あーなるほど…ココで b2Fixture を使うのかー… ^^;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | { std::vector<MyContact>::iterator pos; for (pos = _contactListener->_contacts.begin(); pos != _contactListener->_contacts.end(); pos++) { MyContact contact = *pos; if (((contact.fixtureA == _bottomFixture) && (contact.fixtureB == _ballFixture )) || ((contact.fixtureA == _ballFixture ) && (contact.fixtureB == _bottomFixture))) { CCLOG( "%s Ball hit Bottom!!" , __PRETTY_FUNCTION__); } } } |
シミュレーターで試してみると、XCodeのアウトプットにログが出力されるwww
std::vector … 覚えないと… ^^;;