在3.0版本alpha及其以后,原有的layer类的registerWithTouchDispatcher被弃置,采用全新的
EventDispatcher Mechanism
简单来说,主要包括三个部分:
1.Event Listener 封装事件监听的回调函数
2.Event Dispatcher 事件发生的时候通知Listener
3.Event Objects 携带一些相关的事件信息
就是简单的观察者模式,根据订阅情况,发出事件通知给所有的监听对象
一共有五种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);