Edited at

タッチイベント処理をコードで直接中断させる(cocos2d-x)

More than 3 years have passed since last update.


タッチイベント処理中断

cocos2d-xではEventDispatcherを使ってこんな風にタッチイベントを取得します


GameLayer.cpp

auto touchListner = EventListenerTouchOneByOne::create();

touchListner->setSwallowTouches(true);

touchListner->onTouchBegan = CC_CALLBACK_2(GameLayer::onTouchBegan,this);
touchListner->onTouchMoved = CC_CALLBACK_2(GameLayer::onTouchMoved,this);
touchListner->onTouchEnded = CC_CALLBACK_2(GameLayer::onTouchEnded,this);
touchListner->onTouchCancelled = CC_CALLBACK_2(GameLayer::onTouchCancelled,this);

_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListner, this);


すると、指が離れた、もしくは着信などによってタッチが中断された場合、

onTouchMoved から onTouchEnded or Cancelledにイベントが推移します。

これらはEventDispatcherによって制御されていますが

ここで、タッチイベントの発生とは関係なく、直接タッチをキャンセルさせたい場合

つまりコード側でタッチキャンセルイベントの実行をしたい場合はどうするんでしょうか。

もちろんonTouchCancelld();と呼び出したところで意味はありません。

このメソッド自体は単なるイベントを紐付けたNodeを継承したクラスのメンバ関数であり

タッチイベントのキャンセル自体とは関連がないからです。

ここで、ではさくっとeventDispatcherの実装を見てみます。

すると、こんなパブリックメソッドが見つかります。


CCEventDispatcher.h

public:

////////
void dispatchEvent(Event* event);
////////

イベントを発生させてそうなメソッドです。さて、ここに適したイベントを渡せばキャンセルできそうな感じです。

さて、ここでeventDispatcherの実装を他にも色々と見ると、タッチイベント中断の為にここに渡すべきイベントは、Eventクラスを継承したEventTouchクラスであることが分かります。


CCEventTouch.h

public:

////////
enum class EventCode
{
BEGAN,
MOVED,
ENDED,
CANCELLED
};

EventTouch();

inline EventCode getEventCode() const { return _eventCode; };
inline const std::vector<Touch*>& getTouches() const { return _touches; };

#if TOUCH_PERF_DEBUG
void setEventCode(EventCode eventCode) { _eventCode = eventCode; };
void setTouches(const std::vector<Touch*>& touches) { _touches = touches; };
#endif

////////


かなり見えてきました。

タッチのイベントの種類を示す列挙体と、アクセッサたちです。

これらを上手く構成してeventDispatcherに渡せば、上手く動きそうです。

というわけで、onTouchMoved中に何らかのイベントによってタッチをキャンセルしたい場合、コードはこうなります。


GameLayer.cpp

void GameLayer::onTouchMoved(cocos2d::Touch* touch,cocos2d::Event* event){

////////
EventTouch cancellEvent; //インスタンス作成
cancellEvent.setEventCode(EventTouch::EventCode::CANCELLED); //イベント種類設定
cancellEvent.setTouches(std::vector<Touch*>{touch}); //タッチ情報セット(std::initializer:c++11)

_eventDispatcher->dispatchEvent(dynamic_cast<Event*>(&cancellEvent)); //イベントdispatch
////////
}


これで動くと思います。