Cocos 2 d-x学習(三):タッチスクリーンイベント(単点タッチスクリーン)


cocos 2 d-xでのタッチスクリーンイベントは、マルチタッチスクリーンとシングルタッチスクリーンに分けられますが、マルチタッチスクリーンで使用される場所はそれほど多くないので、まず、シングルタッチスクリーンの使い方と基本原理を主に記録します.
一般的によく使われるタッチスクリーンの場合は2つあります.1つは、Layerがタッチスクリーンメッセージを統一的に受信し、プログラムが必要に応じて異なる位置の精霊に配布することです.もう1つのケースは、Button機能に似たSpriteのようなタッチスクリーンメッセージを受信できるSpriteをカスタマイズすることです.これは、Spriteを定義するときにタッチスクリーンがトリガーする操作を定義する必要があります.
次の2つのケースについて、基本的な使い方をそれぞれ記録します.

1.Layerタッチスクリーンメッセージ受信


使用法は簡単で、親を上書きする4つの方法(必要に応じて書きますが、ccTouchBegan()は上書きする必要があり、その戻り値はタッチスクリーンイベントの伝達に影響します.後でまとめます)を必要とし、init()方法でCCTouchDispacherに追加します.コードは以下の通りです.
class TouchableLayer: public CCLayer 
{
public:
    
    virtual bool init();
    
    LAYER_NODE_FUNC(TouchableLayer);
    
    virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);

    virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);
};

Layerのinit()に次のコードを追加すると、このLayerはタッチスクリーンメッセージを受信できます.
CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, 0, true);

このように具体的に触れるSpriteやエリアなどの情報を判断するには、自分で判断や配布メッセージのコードを書く必要があります!

2.タッチスクリーンメッセージを受信できるSpriteをカスタマイズ


これは少し複雑ですが、まずCCSpriteまたはその親を継承して、精霊の形状、位置などの情報の要求を満たす必要があります.また、タッチスクリーンイベントを継承してCCTargetedTouchDelegateに依頼する必要があります.CCTargetedTouchDelegateでは、タッチスクリーン情報を受信するコールバック虚関数が定義されています.これらの虚関数は、私たちが書き直す必要がある部分です.コードは以下の通りです.
class TouchableSprite: public CCSprite, public CCTargetedTouchDelegate
{
    
public:
    TouchableSprite();
    virtual ~TouchableSprite();
    
    static TouchableSprite *touchSpriteWithFile(const char *file);
    
    bool initWithFile(const char *file);
    
    virtual void onEnter();
    virtual void onExit();
    
    CCRect rect();
    bool containsTouchLocation(CCTouch *touch);
    
    virtual bool ccTouchBegan(CCTouch *touch, CCEvent *event);
    virtual void ccTouchMoved(CCTouch *touch, CCEvent *event);
    virtual void ccTouchEnded(CCTouch *touch, CCEvent *event);

};

ポイントは、カスタムSpriteがクリックされているかどうかを判断することです.この場合、精霊がいる矩形を得る必要があります.この場合、2つの判断方法があります.
(1)タッチパネルの位置を求め,精霊の位置の矩形領域とタッチパネルの点から含むか否かを判断し,含む場合はSpriteに触れたことを示す.ここには、精霊が現在存在する矩形を得る方法が書かれています.
CCRect TouchableSprite::rect()
{
    CCSize size = getContentSize();
    CCPoint pos = getPosition();

    return CCRectMake(pos.x - size.width / 2, pos.y - size.height / 2, size.width, size.height);
}

そしてクリックするたびに現在のタッチパネル位置をGL座標の位置に変換し、Spriteがある矩形と含めて判断する
bool TouchableSprite::containsTouchLocation(cocos2d::CCTouch *touch)
{
    CCPoint touchPoint = touch->locationInView(touch->view());
    touchPoint = CCDirector::sharedDirector()->convertToGL(touchPoint);
    
    return CCRect::CCRectContainsPoint(rect(), touchPoint);
}

(2)cococos 2 dは比較的簡単な方法を提供してくれたが,原理は類似しており,CCノードで定義されたconvertTouchToNodeSpaceAR()法を呼び出し,タッチスクリーン点をノードに対する相対座標に変換する
(ps:デフォルトanchor点は中点なので、各Sprite上の相対座標系は(-width/2,-height/2)から左上角点座標)なので、上記の2つの方法を修正する必要があります
CCRect TouchableSprite::rect()
{
    CCSize size = getTexture()->getContentSize();

    return CCRectMake(-size.width / 2, -size.height / 2, size.width, size.height);
}
bool TouchableSprite::containsTouchLocation(cocos2d::CCTouch *touch)
{
    return CCRect::CCRectContainsPoint(rect(), convertTouchToNodeSpaceAR(touch));
}

3.タッチパネルの伝達順序


また重要なのは
virtual bool ccTouchBegan(CCTouch *touch, CCEvent *event);

メソッドは、このタッチスクリーンメッセージに影響を与える戻り値であり、簡単に言えばfalseを返すと、ccTouchMoved()、ccTouchEnded()、ccTouchCanceld()メソッドを処理せず、後続のタッチスクリーンメッセージを受信するオブジェクト処理に渡すことを示す.trueを返すと、ccTouchMoved()、ccTouchEnded()、ccTouchCanceld()メソッドが処理され、このタッチスクリーンメッセージが消費されることを示します.
以下にまとめる.
1.CLayerが1階のみの場合:
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
a.falseを返すと、ccTouchMoved()、ccTouchEnded()はメッセージを受信しない
b.trueを返すと、ccTouchMoved()、ccTouchEnded()はメッセージを受信することができる
2.CCLayerが多層の場合:
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
a.falseを返すと、本層のccTouchMoved()は、ccTouchEnded()はメッセージを受信しないが、本層の下の他の層はメッセージを受信する
b.trueを返すと、本層のccTouchMoved()、ccTouchEnded()はメッセージを受信できるが、本層の下の他の層はメッセージを受信できない
3.タッチメッセージを受信するスプライトをカスタマイズする場合:
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
a.falseに戻ると、この精霊のccTouchMoved()は、ccTouchEnded()はメッセージを受信しないが、この精霊が存在する層はタッチメッセージを受信する(精霊が存在する層がタッチメッセージを受信するように設定されていない場合は、下に伝達する)
b.trueを返すと、この精霊のccTouchMoved()、ccTouchEnded()はメッセージを受信し続け、そのメッセージを消費する(すなわち、存在するレイヤや他のレイヤに伝達されない)
テストコード