Cocos2d-x的事件分发教程(一)

2015年03月20日 14:04 0 点赞 0 评论 更新于 2025-11-21 17:52

事件系统,从微观层面来看,它是应用程序内部各个模块交互的设计模式;从宏观层面而言,它是软件架构的组成模块。Cocos2d-x 3.x 版本之后,引入了全新的响应用户事件的机制。

事件分发不仅能够处理系统事件,还支持分发自定义事件,并且可以依据元素的绘制顺序来确定处理顺序的优先级,这极大地提升了触摸等事件的管理效率。

教学视频

(原文未提供具体视频信息,此处保留提示)

课程笔记

事件的机制

大多数事件系统采用的是订阅者设计模式。事件是一种用于处理模块之间通信的模型。例如,当模块 A 触发某个事件时,需要调用模块 B 的方法。若模块 A 直接调用模块 B 的方法,那么就需要在模块 A 中对模块 B 进行实例化。一旦模块 B 发生变化,模块 A 可能也需要相应地做出调整。而且,模块 B 和模块 A 可能是完全独立的系统,或者模块 A 无法提前知晓模块 B 的具体情况,甚至在初始阶段模块 B 可能并不存在。

订阅者模式则是将事件的触发者和响应者分离开来。具体流程如下:模块 B 向事件分发器注册一个订阅者 listenb,表明自己需要处理类型为 typeA 的事件消息,listenb 携带一个用于处理事件的回调方法地址 func;当事件发生时,模块 A 向事件分发器发出类型为 typeA 的事件消息通知,并传入参数 args;事件分发器接收到消息后,会从订阅者列表中查找订阅者 listenb,并触发该订阅者的回调函数 func,同时传入参数 args

通过这种方式,事件可以在不依赖响应者具体实现的情况下预先定义,事件响应者甚至可以动态地进行修改或删除。即便某个事件类型没有任何订阅者,该事件也仅仅是不会产生任何响应。

事件系统具有诸多优点:

  1. 降低模块内聚性,保持高效通信:减少了软件内各模块之间的紧密耦合,同时确保模块之间能够高效地进行通信。
  2. 支持事件预定义:使得系统能够提前预定义一些事件,如触摸、加速计等系统事件。
  3. 解除模块耦合:消除了模块之间的相互依赖,使各个模块更加独立。
  4. 灵活的订阅关系:一个事件可以对应多个订阅者(多个订阅者订阅同一类型的事件),多个订阅者也可以对应一个事件源(多个不同类型的订阅者,一个事件源可能引发多种类型的事件。例如,当发生物理碰撞时,物理引擎需要计算碰撞后的位置,AI 系统需要进行数值计算,动画特效系统可能会播放一些动画特效)。

然而,事件系统也存在一定的局限性:

  1. 性能影响:事件系统会对系统性能产生一定影响,因为在搜索订阅者时需要进行排序查询。例如,AI 算法在每帧需要实时更新多个角色的游戏状态,这种场景就不太适合使用事件分发。
  2. 回调函数的局限性:订阅者虽然使用回调函数,但在某些情况下,其效果不如直接调用。

事件的订阅者

订阅者是 EventListener 的子类,例如 EventListenerTouchOneByOne 用于响应触摸事件。每个 EventListener 由一个或多个回调函数、一个订阅者 Type 和一个 listenerID 组成。Type 用于区分不同的 EventListenerlistenerIDType 一一对应(除了 TypeCUSTOM 的情况,此时 listenerID 的数量是无限的);listenerID 又与事件的 Type 相对应,当事件分发器获取到事件 Type 时,就能够得到 listenerID,进而找到对应的事件订阅者。事件包含事件类型和参数,类型与 listenerID 一一对应(触摸事件对应两个事件订阅器 EventListenerTouchOneByOneEventListenerTouchAllAtOnceCUSTOM 事件的参数 eventName 即为 listenerID)。

注册订阅者

可以通过 addEventListenerWithSceneGraphPriorityaddEventListenerWithFixedPriority 方法来注册订阅者。

  • addEventListenerWithSceneGraphPriority:第二个参数为 Node,优先级为 0,顺序按照 node 绘制顺序的反序。
  • addEventListenerWithFixedPriority:第二个参数为 int,不能设置为 0,数字越小优先级越高。当无法判断订阅者关联的 node,且优先级是通过第二个函数设置时,可以使用 setPriority 方法来修改优先级。

删除订阅者

可以使用 removeEventListenerremoveCustomEventListenersremoveAllEventListenersremoveEventListenersForTargetremoveEventListenersForType 方法来删除订阅者。需要注意的是,所有的 EventCustomListenerType 都是 CUSTOM

修改订阅者

当调用 NodeonExit 方法时,会暂停订阅者,调用 onEnter 方法时会恢复订阅者。对于非 Node 的订阅者,需要调用订阅者的 setEnabled 方法来进行修改。

作者信息

boke

boke

共发布了 3994 篇文章