在3.0版本alpha及其之後,原有的layer類的registerWithTouchDispatcher被棄置,採用全新的 node
EventDispatcher Mechanism express
簡單來講,主要包括三個部分: ide
1.Event Listener 封裝事件監聽的回調函數 函數
2.Event Dispatcher 事件發生的時候通知Listener this
3.Event Objects 攜帶一些相關的事件信息 spa
就是簡單的觀察者模式,根據訂閱狀況,發出事件通知給全部的監聽對象 code
一共有五種Event Listner 對象
EventListenerTouch - responds to touch events 事件
EventListenerKeyboard - responds to keyboard events 圖片
EventListenerAcceleration - reponds to accelerometer events
EventListenMouse - responds to mouse events
EventListenerCustom - responds to custom events
每一種對應於不一樣的事件。
使用方法:
1.綁定監聽事件處理函數到監聽對象
2.註冊監聽對象給事件分派機構Event Dispatcher
3.事件發生的時候,發送Event Object給全部的監聽者
在新版本的API當中,能夠使用C++ 11的lamda表達式的方法進行相關設置
在官方的API文檔裏面,有很是詳細的闡釋,基於的例子就是以前編譯的cpp-tests
基本代碼以下
using namespace cocos2d::extension; bool bRet = false; do { CC_BREAK_IF(!CCLayer::init()); auto listener1 = EventListenerTouchOneByOne::create(); listener1->setSwallowTouches(true); listener1->onTouchBegan = CC_CALLBACK_2(SecondScene::onTouchBegan, this); listener1->onTouchMoved = CC_CALLBACK_2(SecondScene::onTouchMoved, this); listener1->onTouchEnded = CC_CALLBACK_2(SecondScene::onTouchEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this); // _eventDispatcher->addEventListener(listener1); this->setTouchEnabled(true);#endif Size size = Director::sharedDirector()->getVisibleSize(); auto sprite1 = Sprite::create("CyanSquare.png"); sprite1->setPosition(Point(size.width / 2, size.height / 2) + Point(-80, 80)); addChild(sprite1, 10); auto sprite2 = Sprite::create("MagentaSquare.png"); sprite2->setPosition(Point(size.width/2, size.height/2)); addChild(sprite2, 20); auto sprite3 = Sprite::create("YellowSquare.png"); sprite3->setPosition(Point(0, 0)); sprite2->addChild(sprite3, 1); //Create a "one by one" touch event listener (processes one touch at a time) auto listener1 = EventListenerTouchOneByOne::create(); // When "swallow touches" is true, then returning 'true' from the onTouchBegan method will "swallow" the touch event, preventing other listeners from using it. listener1->setSwallowTouches(true); // Example of using a lambda expression to implement onTouchBegan event callback function listener1->onTouchBegan = [](Touch* touch, Event* event){ // event->getCurrentTarget() returns the *listener's* sceneGraphPriority node. auto target = static_cast<Sprite*>(event->getCurrentTarget()); //Get the position of the current point relative to the button Point locationInNode = target->convertToNodeSpace(touch->getLocation()); Size s = target->getContentSize(); Rect rect = Rect(0, 0, s.width, s.height); //Check the click area if (rect.containsPoint(locationInNode)) { log("sprite began... x = %f, y = %f", locationInNode.x, locationInNode.y); target->setOpacity(180); return true; } return false; }; //Trigger when moving touch listener1->onTouchMoved = [](Touch* touch, Event* event){ auto target = static_cast<Sprite*>(event->getCurrentTarget()); //Move the position of current button sprite target->setPosition(target->getPosition() + touch->getDelta()); }; //Process the touch end event listener1->onTouchEnded = [=](Touch* touch, Event* event){ auto target = static_cast<Sprite*>(event->getCurrentTarget()); log("sprite onTouchesEnded.. "); target->setOpacity(255); //Reset zOrder and the display sequence will change //更改先後順序,註釋掉的話嚴格按照Z軸的先後順序 if (target == sprite2) { sprite1->setZOrder(100); } else if(target == sprite1) { sprite1->setZOrder(0); } }; //Add listener _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite3); } while (0); return true;
就是載入三個sprite圖片,藍色,紅色,***,默認的順序是,藍色最低層,而***結點是紅色結點的子結點
給三個sprite增長Touch Listner,設置swallow的flag爲true
效果就是,
若是按照上述運行,不註釋掉切換的那一部分code
那麼
Z order的值更大的若是sprite在範圍之內被點擊,會吞噬掉touch事件,不會再往下一層傳輸
若是不採用lamda表達式方式註冊事件,能夠採用以往版本的
auto listener1 = EventListenerTouchOneByOne::create(); listener1->setSwallowTouches(true); listener1->onTouchBegan = CC_CALLBACK_2(SecondScene::onTouchBegan, this); listener1->onTouchMoved = CC_CALLBACK_2(SecondScene::onTouchMoved, this); listener1->onTouchEnded = CC_CALLBACK_2(SecondScene::onTouchEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this);