在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);