Cocos2d-x 事件处理EventDispatcher

Cocos2d-x 事件处理EventDispatcher

声明:本文分析的是cocos2d-x-3.12的代码

Cocos2d-x 3.x中一共有六种事件,如类图所示:

 

 Cocos2d-x 事件处理EventDispatcher_第1张图片

单点触摸事件 (EventListenerTouchOneByOne)

多点触摸事件 (EventListenerTouchAllAtOnce)

键盘响应事件 (EventListenerKeyboard)

鼠标响应事件 (EventListenerMouse)

自定义事件 (EventListenerCustom)

加速记录事件 (EventListenerAcceleration)

 

Cocos2d中所有的事件统一由EventDispatcher类管理,和Action动作、Scheduler调度器的管理一样,分发器EventDispatcher类只在Director类中有一共实例EventDispatcher* Director:: _eventDispatcher

 

Cocos2d中事件采用订阅的方式,当需要处某种类型的事件时,可以向分发器EventDispatcher类订阅,当对应的事件Event发生时,EventDispatcher类会调用回调函数,通知订阅者。

 

 Cocos2d-x 事件处理EventDispatcher_第2张图片

监听器EventListener和事件Event

当要处理某事件时,首先要创建一共监听器,并设置好回调函数,然后通过EventDispatcher类中的addEventListenerXXX()函数订阅事件,有事件发生时会调用回调函数。

例如,触摸事件:

    //创建监听器

    auto touchLis = EventListenerTouchOneByOne::create();

    //设置回调函数

    touchLis->onTouchBegan= [](Touch *t, Event *e) ->bool { returntrue; };

    touchLis->onTouchMoved= [](Touch *t, Event *e) { };

    touchLis->onTouchEnded= [](Touch *t, Event *e) {};

    //订阅事件

    _eventDispatcher->addEventListenerWithFixedPriority(touchLis, 1);

事件处理都是采用C++11的回调函数,可以通过std::bind绑定事件处理的额外参数,如this指针等等。Cocos提供了以下几个宏(调用了std::bind)绑定参数

CC_CALLBACK_0CC_CALLBACK_1CC_CALLBACK_2CC_CALLBACK_3

 

EventListenerTouchOneByOne和EventTouch

EventListenerTouchOneByOne 单点触控事件,每次触控都只有一个触点的点击事件。

 

触控事件的回调函数

 

回调函数类型

typedef std::function<bool(Touch*, Event*)>  ccTouchBeganCallback;

typedef std::function<void(Touch*, Event*)>  ccTouchCallback;

参数Touch,存放了触点信息,可以通过Touch::getLocation函数获取触点的世界坐标。可以通过Node::convertToNodeSpace函数转换成节点的本地坐标

参数Event,这个参数是一个EventTouch类,可以强制转换成EventTouch类。EventTouch类存放了关于触摸事件的信息,包括Touch参数。

 

ccTouchBeganCallback onTouchBegan; //点击按下事件

事件有一个bool返回值

如果返回ture 后面才会接收到onTouchMovedonTouchEndedonTouchCancelled事件。返回true的情况下并且监听器设置了_needSwallow参数为ture,则回停止传递事件,后续的EventListenerTouchOneByOne则接收不到相应的事件。

如果返回false 后续的onTouchMovedonTouchEndedonTouchCancelled都会接收不到,且事件也回继续往后传递。

ccTouchCallback onTouchMoved;      //点击后移动事件

ccTouchCallback onTouchEnded;      //点击抬起事件

ccTouchCallback onTouchCancelled//点击取消事件,如手机来电话

 

 

void EventListenerTouchOneByOne::setSwallowTouches(bool needSwallow)

该函数可以设置是否停止传递触摸事件

 

EventListenerTouchAllAtOnce和EventTouch

EventListenerTouchAllAtOnce 多点触控事件,一个点触摸时也会收到该事件。

回调函数

typedef std::function<void(conststd::vector<Touch*>&, Event*)>

参数std::vector&,存放了多个触点信息,

参数Event,这个参数是一个EventTouch类,可以强制转换成EventTouch类。EventTouch类存放了关于触摸事件的信息,包括std::vector参数。

ccTouchesCallback;

ccTouchesCallback onTouchesBegan;   //点击按下事件

ccTouchesCallback onTouchesMoved;   //点击后移动事件

ccTouchesCallback onTouchesEnded;   //点击抬起事件

ccTouchesCallback onTouchesCancelled; //点击取消事件,如手机来电话

 

EventListenerKeyboard和EventKeyboard

 

回调函数

std::function<void(EventKeyboard::KeyCode, Event*)> onKeyPressed; //按键按下

std::function<void(EventKeyboard::KeyCode, Event*)> onKeyReleased; //按键弹起

参数KeyCode,EventKeyboard::KeyCode枚举值,代表了那个按键

参数Event,实际是一共EventKeyboard类,可以强制转换。

 

EventListenerMouse和EventMouse

回调函数

std::function<void(EventMouse* event)> onMouseDown//鼠标按下

std::function<void(EventMouse* event)> onMouseUp;    //鼠标弹起

std::function<void(EventMouse* event)> onMouseMove//鼠标移动

std::function<void(EventMouse* event)> onMouseScroll; //鼠标滚轮滚动

参数EventMouse,包含了鼠标点击的信息

getMouseButton获取鼠标按键 -1代表没有按键信息,0代表左键,1代表右键,2代表滚轮键

         getLocation获取鼠标位置

         getCursorY获取滚轮竖向滚动量

         getCursorX获取滚轮横向滚动量

 

EventListenerAcceleration和EventAcceleration

加速器事件

回调函数

std::function<void(Acceleration*, Event*)> onAccelerationEvent;

参数Acceleration,加速器信息

参数Event,实际是一个EventAcceleration类,可以强制转换。

 

EventListenerCustom和EventCustom

自定义事件,用户可以自己定义一些事件然后,可以通过EventDispatcher::dispatchEvent函数发送自定义事件。

回掉函数

std::function<void(EventCustom*)> _onCustomEvent;

EventListenerCustom在创建是需要指定一个字符串类型的关键字,这个关键字用来区分自定义事件的类型。

参数EventCustom

getEventName函数获取自定义事件的类型

setUserData函数  设置额外的事件参数

getUserData函数  获取事件的额外参数

 

系统中默认会在绘制场景时发送一些自定义事件,通知绘制信息

主要如以下自定义事件:

_eventProjectionChanged转换矩阵发生变化时发送

_eventAfterDraw         绘制节点后发送

_eventAfterVisit        遍历场景后时发送

_eventBeforeUpdate      处理调度器前发送

_eventAfterUpdate       处理调度器后发送

_eventResetDirector     导演类被重置时发送

 

Event类

Event类有六个派生类EventAcceleration、EventCustom、EventKeyboard、EventMouse、EventTouch分别对应相应的事件,在Listener中会传递相应的事件类型给回调函数。

 

函数

获取事件类型 TOUCH、KEYBOARD、ACCELERATION、MOUSE、CUSTOM等等

    inlineType getType() const { return_type; };

 

停止事件传递,设置后事件回停止传递给后续监听器

inline void stopPropagation() { _isStopped = true; };

 

设置所属节点,如果是fixedPriority监听器则返回null。否则返回addEventListenerWithSceneGraphPriority参数对应的node节点。

    inline Node* getCurrentTarget() { return_currentTarget; };

 

 

分发器EventDispatcher类

Cocos中所有的事件都由EventDispatcher类管理,在Director类中有唯一的一个初始化实例    EventDispatcher* Director::_eventDispatcher;,在Director::init函数中进行了初始化。

    _eventDispatcher = new (std::nothrow) EventDispatcher();

 

函数接口

订阅事件,添加监听器

//以节点node的绘制顺序的优先级作为处理事件优先级添加监听器,绘制在屏幕前面的节点优先级更高。该监听器会在节点node释放是移除。Node类的析构函数中调用的移除监听器函数。

void addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node);

 

//以固定优先级添加监听器。fixedPriority小于0,则优先级高于SceneGraphPriority;大于0,则低于SceneGraphPriority。不可用等于0,等于0留给了SceneGraphPriority用。

void addEventListenerWithFixedPriority(EventListener* listener, intfixedPriority);

 

以固定优先级1,添加一个定制事件监听器。函数内部会创建一个定制事件监听器,类监听器要手动移除。

EventListenerCustom* addCustomEventListener(conststd::string &eventName, conststd::function<void(EventCustom*)>& callback);

 

移除监听器

    void removeEventListener(EventListener* listener);

    void removeEventListenersForType(EventListener::TypelistenerType);

    void removeEventListenersForTarget(Node* target, boolrecursive = false);

    void removeCustomEventListeners(conststd::string& customEventName);

    void removeAllEventListeners();

暂停监听器事件

    void pauseEventListenersForTarget(Node* target, boolrecursive = false);

恢复监听器

    void resumeEventListenersForTarget(Node* target, boolrecursive = false);

禁用/开启事件

    void setEnabled(boolisEnabled);

发送事件

         所有的事件都可以通过该函数方式,更加Event的类型发送相应类型的事件。

    void dispatchEvent(Event* event);

    发送自定义事件

    void dispatchCustomEvent(const std::string &eventName, void *optionalUserData = nullptr);

 

监听器的管理

EventDispatcher类有一个按事件类型分类的Map变量存储了所有注册的listener。

std::unordered_map<EventListener::ListenerID, EventListenerVector*> _listenerMap;

这个Map的数据变量EventListenerVector,里面会有两个EventListener数组。

        std::vector<EventListener*>*_fixedListeners;

        std::vector<EventListener*>*_sceneGraphListeners;

这两个数组分别存储了固定优先级的监听器和SceneGraphPriority的监听器。

当调用addEventListenerWithSceneGraphPriority函数时会添加到sceneGraphListeners中,调用addEventListenerWithFixedPriority函数和addCustomEventListener函数时会添加到fixedListeners中。添加完后会设置一个标识代表要下次访问需要排序。流程图如下:

 

 Cocos2d-x 事件处理EventDispatcher_第3张图片

事件的发送

事件发送是通过EventDispatcher::dispatchEvent函数实现的,函数会先检查是否要排序,如果需要则会对监听器进行排序。排序完成后再按排序后的监听器逐一分发事件。具体流程图大致如下:

 

 Cocos2d-x 事件处理EventDispatcher_第4张图片

你可能感兴趣的:(Cocos2d-x)