cocos2dx+lua学习笔记:事件派发器CCEventDispatcher

前言
本篇在讲什么

cocos2dx内关于事件监听和派发的调度器EventDispatcher相关内容
本篇适合什么

适合初学Cocos2dx的小白
适合想要学习EventDispatcher的新手

本篇需要什么

Lua语法有简单认知
C++语法有简单认知
Cocos2dx有简单认知
Cocos2dx-Lua的开发环境
依赖Visual Studio编辑器

本篇的特色

具有全流程的图文教学
重实践,轻理论,快速上手
提供全流程的源码内容


★提高阅读体验★

👉 ♠ 一级标题 👈

👉 ♥ 二级标题 👈

👉 ♣ 三级标题 👈

👉 ♦ 四级标题 👈


♠ CCEventDispatcher在干什么

观察者模式是我们最常用的设计模式之一,事件系统就是基本的观察者模式用法,举个简单的例子:

在这里插入图片描述

1、A店员根据号码派发餐饭,号码是类型,喊号码给饭
2、B顾客会在喊道38号时取餐,B顾客监听38号类型

以上就是一个最简单的事件监听和派发的例子,而EventDispatcher处理的就是上述事件的注册和监听


♠ 事件的监听和派发

派发器内提供了事件监听、派发以及取消监听的接口,下述内容中我们将简单认识相关接口的功能和使用


♥ 监听

从头文件中我们可以看到一共提供了三种供我们使用的监听注册方式

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

void addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority);

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

♣ addEventListenerWithSceneGraphPriority

该方法为某个Node添加指定事件类型的监听,比如:给按钮A添加点击事件

  • 参数

listener:监听事件的类型

node:监听事件绑定的节点

  • 特点

节点销毁、监听销毁
同场景下,渲染越靠前,监听越靠前

在这里插入图片描述

点击两个图片交界处,黄色图片注册的事件执行早于红色图片注册的事件

  • 常用事件类型
EventListenerTouchOneByOne      // 单点事件
EventListenerTouchAllAtOnce     // 多点事件
EventListenerMouse              // 鼠标
EventListenerKeyboard           // 键盘
EventListenerFocus              // 聚焦
EventListenerAcceleration       // 加速剂(陀螺仪)

♣ addEventListenerWithFixedPriority

为指定事件添加固定优先级的监听

  • 参数

listener:监听事件的类型

fixedPriority:优先级

  • 特点

不绑节点,不会自动销毁,注册后一直存在
设置优先级越低,执行顺序越靠前

  • 常用事件类型
EventListenerCustom     // 自定义事件

♣ addCustomEventListener

添加自定义事件监听器,用的比较少,一般上边俩方法基本满足需要了

  • 参数

eventName:事件名,字符串

callback:监听到事件后的执行回调

  • 返回值

生成好的事件类型,绑定了事件名和回调

  • 特点

不和节点,不会自动销毁,注册后一直存在
固定优先级为1


♥ 取消监听

取消监听有很多种不同的方式,也有根据注册方式存在特定的取消方式

void removeEventListener(EventListener* listener);

void removeEventListenersForType(EventListener::Type listenerType);

void removeEventListenersForTarget(Node* target, bool recursive = false);

void removeCustomEventListeners(const std::string& customEventName);

void removeAllEventListeners();

♣ removeEventListener

根据注册事件时使用的事件类型来取消监听

  • 参数

listener:和注册时使用的事件类型(同一个)


♣ removeEventListenersForType

删除某个类型所有的监听事件

  • 参数

listenerType:和注册时使用的事件类型(同一个)

  • 类型枚举
    enum class Type
    {
        TOUCH_ONE_BY_ONE,       // 单点触摸
        TOUCH_ALL_AT_ONCE,      // 多点触摸
        KEYBOARD,               // 键盘
        MOUSE,                  // 鼠标
        ACCELERATION,           // 加速剂
        FOCUS,                  // 焦点
        CUSTOM                  // 自定义
    };

♣ removeEventListenersForTarget

删除与指定目标相关联的所有侦听器

  • 参数

target:目标节点
recursive:是否删除子节点的所有侦听器,默认false


♣ removeCustomEventListeners

删除所有具有相同事件名称的自定义监听器

  • 参数

customEventName:自定义的事件名字


♣ removeAllEventListeners

删除所有监听器


♥ 暂停和恢复

我们可以针对某个节点暂停其监听的功能


♣ pauseEventListenersForTarget

暂停与指定目标相关联的所有侦听器

  • 参数

target:目标节点
recursive:是否暂停子节点的所有侦听器,默认false


♣ resumeEventListenersForTarget

恢复与指定目标相关联的所有侦听器

  • 参数

target:目标节点
recursive:是否暂停子节点的所有侦听器,默认false


♥ 派发

相较于监听的多样性,事件的派发就显得相当简洁了,提供两个接口以供事件的派发

void dispatchEvent(Event* event);

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

♣ dispatchEvent

分派事件,根据事件类型

  • 参数

event:事件类型


♣ dispatchCustomEvent

发送带有事件名称的自定义事件和可选的用户数据

  • 参数

eventName:自定义的事件名字_
optionalUserData:自定义事件类型EventCustom的userData字段,自定义的_


♠ 事件监听和派发的实现原理

我们已经知道了事件是如何监听和派发的,下面我们简单了解一下其具体的实现原理


♥ 事件监听后发生了什么

稍微追一下代码,我们可以发现监听注册后,所有的监听事件根据优先级被存进了两个数组内

在这里插入图片描述

std::vector<EventListener*>* _fixedListeners;
std::vector<EventListener*>* _sceneGraphListeners;

♥ 派发是如何进行的

在导演类Director内可以看到,在实例派发器后,每次绘制都会调用派发器的dispatchEvent方法,方法内会根据事件类型去寻找监听列表内符合条件的监听执行

在这里插入图片描述
在这里插入图片描述


♠ 用法小例

因为博主主要用的是cocos2dx+lua,所以这里提供几个lua写的用法小例子


♥ 绑定节点事件

  • 为一个Layer注册了一个点击开始事件
-- 执行回调
local func1 = function()
end
-- 绑定节点
local layer = cc.LayerColor:create(cc.c4b(255, 255, 0, 255))
hummer.scene:addChild(layer)
layer:setContentSize(cc.size(100,100))
-- 事件类型
local listener = cc.EventListenerTouchOneByOne:create()
listener:registerScriptHandler(func1,cc.Handler.EVENT_TOUCH_BEGAN)
-- 注册监听事件
local eventDispatcher = layer:getEventDispatcher()
layer.cacheEventListener = listener
eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layer)

♥ 自定义事件

  • 注册一个名为event_enter_game的自定义事件
-- 注册
local enterGameFunc = function()
end

local listener = cc.EventListenerCustom:create("event_enter_game", enterGameFunc)
cc.Director:getInstance():getEventDispatcher():addEventListenerWithFixedPriority(listener, 1)

-- 派发
cc.Director:getInstance():getEventDispatcher():dispatchCustomEvent("event_enter_game")

♠ 推送

  • Github
https://github.com/KingSun5

♠ 结语

若是觉得博主的文章写的不错,不妨关注一下博主,点赞一下博文,另博主能力有限,若文中有出现什么错误的地方,欢迎各位评论指摘。

👉 本文属于原创文章,转载请评论留言,并在转载文章头部著名作者出处👈
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值