详细解析cocos2dx 3.x的事件中的点击事件

一,总述

cocos的事件分为大概6种,分别为屏幕点击事件、键盘输入、鼠标点击、加速度事件、focus、自定义事件,对事件的操作施行的是监听机制,就是每种事件都有一个监听者类型,其中前5种监听者类型如下所示:

详细解析cocos2dx 3.x的事件中的点击事件_第1张图片

自定义事件需要自己继承EventListener来实现,这里不再进一步描述,下面详细详解下屏幕点击事件。


二,点击事件

点击事件可以分为两种,一种是单点触控,另一种是多点触控,实现的机制可以简单描述为监听、派发机制,即对每个事件都可以添加若干个监听者,按照优先级和渲染层级对监听者们进行排序,然后将事件依次派发给排好序的监听者们,如果其中某个监听者中断了监听(后面介绍中断的情况),则事件不再向后面的监听者派发。

多说无益,看代码!

 auto listener = EventListenerTouchOneByOne::create();
    listener->setSwallowTouches(true);
    listener->onTouchBegan = CC_CALLBACK_2(Paddle::onTouchBegan, this);
    listener->onTouchMoved = CC_CALLBACK_2(Paddle::onTouchMoved, this);
    listener->onTouchEnded = CC_CALLBACK_2(Paddle::onTouchEnded, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

1、上面的代码执行的是添加监听者这个步骤,this指针是被监听者(可以是任一Node对象),EventListenerTouchOneByOne表明监听的是单点触控,多点触控是EventListenerTouchAllAtOnce,最后一句addEventListenerWithSceneGraphPriority是将监听者添加到事件派发管理器中,这样当你点击到被监听者时,就会触发相应的事件,该方法注册的优先级为0。

还有一个addEventListenerWithFixedPriority,这个函数的作用同样是将监听者添加到事件派发管理器中,不过他的监听对象是优先级,这个优先级是我们自己

设置的,我们可以设为除0外的任一整数。

2、下面前三个函数的作用是用来按照优先级对监听者们进行排序,最后一个是按照渲染层级的遍历监听者,具体实现可自行查阅

void sortEventListeners(const EventListener::ListenerID& listenerID);

    void sortEventListenersOfSceneGraphPriority(const EventListener::ListenerID& listenerID, Node* rootNode);

    void sortEventListenersOfFixedPriority(const EventListener::ListenerID& listenerID);
	void visitTarget(Node* node, bool isRootNode);  

3、事件派发,这是最复杂最难完全理解的步骤

按照优先级小—>大的顺序将事件依次派发给监听者,所有的监听者会依次进行touchBegan的处理,再所有监听者touchBegan处理完成后再依次进行move、end和cancle的处理。举个例子,我们有三个监听者,一个被监听者

// 被监听者
    auto sprite1 = Sprite::create("HelloWorld.png");
this->addChild(sprite1);


// 监听者1,监听sprite1
auto listener1 = EventListenerTouchOneByOne::create();
listener1->setSwallowTouches(true);
listener1->onTouchBegan = [](Touch* touch, Event* event)->bool{
CCLOG("listener1 onTouchBegan");
return true;
};
listener1->onTouchMoved = [](Touch* touch, Event* event){CCLOG("listener1 onTouchMoved");};
listener1->onTouchEnded = [](Touch* touch, Event* event){CCLOG("listener1 onTouchEnded");};
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);


// 监听者2,监听优先级1
auto listener2 = EventListenerTouchOneByOne::create();
listener2->setSwallowTouches(true);
listener2->onTouchBegan = [](Touch* touch, Event* event)->bool{
CCLOG("listener2 onTouchBegan");
return true;
};
listener2->onTouchMoved = [](Touch* touch, Event* event){CCLOG("listener2 onTouchMoved");};
listener2->onTouchEnded = [](Touch* touch, Event* event){CCLOG("listener2 onTouchEnded");};
_eventDispatcher->addEventListenerWithFixedPriority(listener2, 1);


// 监听者3,监听优先级-1
auto listener3 = EventListenerTouchOneByOne::create();
listener3->setSwallowTouches(true);
listener3->onTouchBegan = [](Touch* touch, Event* event)->bool{
CCLOG("listener3 onTouchBegan");
return true;
};
listener3->onTouchMoved = [](Touch* touch, Event* event){CCLOG("listener3 onTouchMoved");};
listener3->onTouchEnded = [](Touch* touch, Event* event){CCLOG("listener3 onTouchEnded");};
_eventDispatcher->addEventListenerWithFixedPriority(listener3, -1);

当事件派发时,首先listener3收到事件,因为他的优先级最低,为-1,在listener3处理事件时,首先会输出“listener3 onTouchBegan”,然后判断①是否吞掉事件和②onTouchBegan函数是否返回true,如果①和②均为是,则事件派发管理器中断事件派发,后面的listener1和listener2就接收不到事件了,但listener3的move和end会继续处理。输出如下:

详细解析cocos2dx 3.x的事件中的点击事件_第2张图片

如果设置吞掉事件为否,而onTouchBegan函数返回为true,则事件继续向下派发,直到事件被中断,然后再进行move、end、cancle的处理。输出如下:

详细解析cocos2dx 3.x的事件中的点击事件_第3张图片


如果设置吞掉事件为是,而onTouchBegan函数返回为false,则事件同样继续向下派发,与上面不同的是因为onTouchBegan函数返回为false,所以listener3的move、end、cancle不再处理。输出如下:

详细解析cocos2dx 3.x的事件中的点击事件_第4张图片

总结,事件是否向下派发主要受两个因素影响:是否吞掉事件、touchBegan是否返回false。

结束了,好累!orz....


你可能感兴趣的:(详细解析cocos2dx 3.x的事件中的点击事件)