Box2d をやってみる… チュートリアル2 (9) b2ContactListener

Box2D and Collisions
物体が衝突したときにイベントリスナー的なメソッドを呼び出させる仕組みがあるみたい。
今日はそこを試してみようと思います。

std::vector と b2ContactListenerを継承したクラス の扱い方…
やべーこういう実装…経験した事がないww ^^; …とりあえず写経www ^^;;;

まずは b2ContactListener を継承するクラスを追加(MyContactListener) と、std::vector に格納するための 構造体 MyContact を準備します。

 

//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);
};
#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 で、まず変数定義してクラス変数を準備ですね。

//HelloWorldScene.h

#include "MyContactListener.h"

class HelloWorld : public cocos2d::CCLayer
{
//...(省略)
protected:
    MyContactListener * _contactListener;
//...(省略)
};

aaa

//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 を使うのかー… ^^;

    {
        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 … 覚えないと… ^^;;


Add a Comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です