Lab

Cocos2d-x:Box2Dのスプライトをタップできるようにする

 Tag :  Published : 2013-10-16

Pocket

Box2Dで生成するPhysicsSpriteをタップすると、それぞれのタグが出力されるようにしてみます。

1.プロジェクトの準備

テスト用という事で、テンプレートを使用します。
XcodeメニューのFile->New->ProjectでBox2D用のテンプレートを選んで、プロジェクトを作成します。

Box2D用のテンプレートを選んで、プロジェクトを作成
cocos2dx_box2dを選択

そのまんまシミュレートすると、こんな感じですよね。
タップした場所から、ボックスがポンポン出てきます。

Box2D用のテンプレートをシミュレート

2.タップでボンボン出るのを一回止めて、最初に10個出るようにする

検証しづらいので、タップでボンボン出るのを一回コメントアウトして

void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
    //Add a new body/atlas sprite at the touched location
    CCSetIterator it;
    CCTouch* touch;
    
    for( it = touches->begin(); it != touches->end(); it++) 
    {
        //途中省略
  
        //いったんコメントアウト      
        //addNewSpriteAtPosition( location );
    }
}
    

最初に10個出るようにしちゃいます。

HelloWorld::HelloWorld()
{
    setTouchEnabled( true );
    setAccelerometerEnabled( true );
    
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    // init physics
    this->initPhysics();

    CCSpriteBatchNode *parent = CCSpriteBatchNode::create("blocks.png", 100);
    m_pSpriteTexture = parent->getTexture();
    
    addChild(parent, 0, kTagParentNode);
    
    //このfor文を追加
    for(int i=0; i<10; i++){
        addNewSpriteAtPosition(ccp(s.width/2, s.height/2));
    }

    //以下省略
}
    

3.タグ用変数の追加

検証用に、スプライトにタグを付けてみます。
適当な所にtagNumを用意します。

class HelloWorld : public cocos2d::CCLayer {
    //途中省略
    private:
        //これを追加
        int tagNum;
};
    

4.スプライトにタグを付ける

スプライトが作成されるタイミングでタグを付けます。

void HelloWorld::addNewSpriteAtPosition(CCPoint p)
{
    CCLOG("Add sprite %0.2f x %02.f",p.x,p.y);
    CCNode* parent = getChildByTag(kTagParentNode);
   
    int idx = (CCRANDOM_0_1() > .5 ? 0:1);
    int idy = (CCRANDOM_0_1() > .5 ? 0:1);
    PhysicsSprite *sprite = new PhysicsSprite();
    sprite->initWithTexture(m_pSpriteTexture, CCRectMake(32 * idx,32 * idy,32,32));
    sprite->autorelease();

    //この2行を追加
    sprite->setTag(tagNum);
    tagNum++;

    //以下は省略
}
    

5.タッチイベントを取得可能にする 1

ボックスをタッチできるようにします。
PhysicsSpriteにCCTargetedTouchDelegateを継承させます。

//CCTargetedTouchDelegateを継承
class PhysicsSprite : public CCSprite, public CCTargetedTouchDelegate
{
public:
    PhysicsSprite();
    void setPhysicsBody(b2Body * body);
    virtual bool isDirty(void);
    virtual cocos2d::CCAffineTransform nodeToParentTransform(void);
    
    //この4行を追加
    static PhysicsSprite* create(const char *pszFileName);
    virtual void onEnter();
    virtual void onExit();
    virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);

private:
    b2Body* m_pBody; 
};
    

6.タッチイベントを取得可能にする 2

onEnter、onExit、ccTouchBeganを作ります。

void PhysicsSprite::onEnter(){
    CCSprite::onEnter();
    CCTouchDispatcher* dispatcher = CCDirector::sharedDirector()->getTouchDispatcher();
    dispatcher->addTargetedDelegate(this, 0, true);
}

void PhysicsSprite::onExit(){
    CCSprite::onExit();
    CCTouchDispatcher* dispatcher = CCDirector::sharedDirector()->getTouchDispatcher();
    dispatcher->removeDelegate(this);
}

bool PhysicsSprite::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent){
    CCPoint point = pTouch->getLocation();
    CCSize size = this->getTexture()->getContentSize();
    
    //ボックスの境界を取得して
    CCRect rect = CCRectMake(this->getPositionX()-size.width/2, this->getPositionY()-size.height/2, size.width, size.height);

    //ボックスのタグを取得して
    int tag = this->getTag();

    //タッチした場所がボックスの境界内だったらタグを出力
    if(rect.containsPoint(point)){
        CCLog("%d", tag);
    }

    return rect.containsPoint(point);
}
    

7.完成と思いきや・・・

さあ、これでシミュレートするとボックスが10個出てきて、タップするとそれぞれのタグが出力される・・・と思ったのですが、タップしても何も起きません。
そしてなんと、ボックスが最初に表示された場所をタップすると、ちゃんと出力されるのです。

ボックスをタップしてもタグが出力されない
ボックスが最初に出現した場所(矢印のあたり)をタップすると、タグが出力されます。

8.最後にこの一行

もう一息!
最後にこれを追加します!

void HelloWorld::addNewSpriteAtPosition(CCPoint p)
{
    //途中省略

    // Define the dynamic body.
    //Set up a 1m squared box in the physics world
    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);

    //これを追加!!
    bodyDef.userData = sprite;
}
    

これで今度こそ、ボックスをクリックしたらタグが出力されます。

pageTop