Cocos2d-x的事件分发教程(二)
当订阅者成功注册到事件分发器后,事件分发器需要依据接收到的相应事件进行分发操作。本节课将着重讲解如何进行事件分发。
教学视频
(此处应补充教学视频的相关链接或说明)
课程笔记
事件的触发
事件的触发可通过 dispatchEvent 或者 dispatchCustomEvent 函数来实现。dispatchCustomEvent 会自动创建一个 CustomEvent;也可以先手动创建一个 CustomEvent 类型的事件对象,然后使用 dispatchEvent 方法来触发该事件。
事件的分发
在 dispatchEvent 函数中,主要完成了对 listenerID 对应订阅者的排序工作,按照排序后的顺序依次调用订阅者的回调函数,最后更新事件分发的状态。
在对 listenerID 对应订阅者进行排序时,具体步骤如下:
- 首先将优先级列表按照从小到大的顺序排列。
- 找到第一个优先级大于 0 的订阅者索引。
- 接着将
Node对应的订阅者列表按照绘制顺序进行排序。
需要注意的是,频繁排序会导致性能问题。为了解决这个问题,EventDispather 采用了做标记的方法。当对做了标记的 listenerID 进行变动时,就会重新进行排序;否则,不会进行重新排序。在以下函数中会进行标记操作:setLocalZOrder、setGlobalZOrder、setPriority、forceAddEventListener、removeEventListener。如果关联的 Node 或者关联 Node 的父类 Node 发生 Z 变换,也需要重新排序。
事件允许嵌套,即在事件的回调函数中可以调用 dispatchEvent 触发另外一个事件。在函数中通过 DispatchGuard guard(_inDispatch); 进行标记,其中 _inDispatch 初始值为 0,在进行 dispatch 操作时加 1,当该标记的生命周期结束时减 1。需要特别注意的是,在嵌套事件中不能执行相同的事件,否则会导致死循环。
在事件分发的过程中,优先级高的订阅者可以通过 event 的 stopPropagation 方法选择让事件停止传播。
订阅者的修改
- 优先级修改:在事件分发的过程中修改订阅者的优先级,该修改会在下一次触发事件时生效。
- 状态修改:通过
setEnable、setPause、setRegistered方法对订阅者状态进行修改,这些修改会即时生效。 - 订阅者删除:在事件分发的过程中删除订阅者,只是将其标记为
setRegistered(false),在分发结束时才会真正将其从订阅者列表中移除。 - 订阅者添加:在事件分发的过程中添加订阅者,只是将其加入临时数组
_toAddedListeners,在所有事件分发结束后,才会将其加入订阅者列表。
事件与 Node
- 当调用
Node的onExit方法时,会调用Node及其子Node的pause函数。在pause函数中,会调用pauseEventListenersForTarget方法。 - 当调用
Node的OnEnter方法时,会调用Node及其子Node的resume函数。在resume函数中,会调用resumeEventListenersForTarget方法。 - 删除
Node时,会自动移除和该Node相关的订阅者。