![游戏开发实战宝典](https://wfqqreader-1252317822.image.myqcloud.com/cover/212/44175212/b_44175212.jpg)
2.8 事件机制
事件机制是目前非常主流的程序设计方式,很多引擎和框架都采用这种设计方式,所以能够正确理解事件机制是使用这些引擎和框架的关键。
2.8.1 Egret事件处理机制
在Egret里,事件机制主要是由事件发布者、事件和事件监听者协同完成的。所有的事件发布者类都要继承于egret.EventDispatcher类,所有的事件类都要继承于egret.Event类,至于事件监听者,则没有规定要继承于哪个类。
打个比方,事件发布者就像发布新闻的机构,新闻就是一种事件,当然还有订阅新闻的人,这种人就是事件的监听者。接下来就用这种比喻来写个项目。下面通过代码来展示事件处理机制的使用方法。
创建一个称为“Event”的项目,删除 src 文件夹内的所有文件。然后创建一个称为NewsEvent.ts的类文件,做出如下修改:
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/55_01.jpg?sign=1739523325-AuFTwFzfEUWeakJESQkgPd4kgmAS7kE9-0-1ac7c49dfac5beda4b632502c69b543d)
NewsEvent就是一个事件类,其中的content字段就是事件携带的数据。egret.Event类的构造函数的原型如下:
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/55_02.jpg?sign=1739523325-117PcXsuo6hd8Oard3quywbnc5Ku0aeu-0-43e9c2bcb32bf3a6d452381755b082bb)
以下是对各个参数的解释:
● type:事件的类型,可以作为Event.type进行访问。
● bubbles:确定 Event 对象是否参与事件流的冒泡阶段。默认值为false。
● cancelable:确定是否可以取消Event对象。默认值为false。
● data:与此事件对象关联的可选数据。
接着再创建一个称为NewsDispatcher的类文件,并对其做出如下修改,参见二维码2-28:
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/55_03.jpg?sign=1739523325-lCg2gSiRyNHbYSIsFkShOBpcFlw66jIo-0-c79df2fa2ed01d0b8a0a070d20d5e895)
二维码2-28
NewsDispatcher类就是事件发布者类,类似新闻发布机构。
接下来创建一个称为NewsReader的类文件,参见二维码2-29:
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/55_04.jpg?sign=1739523325-YIY59QsgC8jFpVBsegyGo4JRi2xeuxtQ-0-93546cc8ab8ed8637161dd17cdc8b258)
二维码2-29
NewsReader类就是事件监听者类。接下来看一下以上三个类如何协同工作。首先创建一个称为Main的类文件如下,参见二维码2-30:
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/55_05.jpg?sign=1739523325-1U7ZfXWWfzp99a5zDCmtxGqWtyBjyClM-0-4e2bb6402b991b4a3d0c26dfa5437b3e)
二维码2-30
运行调试播放器,会看到调试窗口的输出,如图2-51所示:
在 NewsDispatcher 类代码的第9 行,该类的对象通过继承的dispatchEvent方法来向已注册的监听者发布事件。在Main类代码的第12~15行,EventDispatcher的子类通过addEventListener方法来注册事件监听者。以下是addEventListener方法的原型:
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/55_06.jpg?sign=1739523325-eUnOgyzXpx3b8v44OQ9nkhA0SHCUMfWr-0-3a8acd9dfc2ff1e6e572729b0a577dd3)
图2-51 程序控制台输出
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/55_07.jpg?sign=1739523325-m7FElweLMocFIXVYQLpu9UIQBmkJYjiT-0-1e076d31a0bf5fed2e0ce5977238dad3)
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/56_01.jpg?sign=1739523325-kSBWUBI6560afEmMi6f5vXREHqU3HKdk-0-a589f9c293e53c688030507830fb6eed)
以下是对各个参数的解释:
● type:事件类型。
● listener:事件处理的函数。
● thisObject:事件处理函数的作用域。
● useCapture:确定侦听器是运行于捕获阶段还是运行于冒泡阶段,可选。设置为 true,则侦听器只在捕获阶段处理事件,而不在冒泡阶段处理事件。设置为 false,则侦听器只在冒泡阶段处理事件。
● priority:事件侦听器的优先级,可选。优先级由一个带符号的整数指定。数字越大,优先级越高。优先级为n 的所有侦听器会在优先级为n-1 的侦听器之前得到处理。如果两个或更多个侦听器共享相同的优先级,则按照它们的添加顺序进行处理。默认优先级为0。
当然还可以移除监听器,对应的方法是removeEventListener,其原型为:
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/56_02.jpg?sign=1739523325-uUj70T4S7j9WPW12FWRBSqUmFYeazhv8-0-774f275a3a7cf9af1f4d8353b5d4e6ed)
以及是否含有监听器:
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/56_03.jpg?sign=1739523325-ehd7y3EwQxH9GY1l7ZRrLOMMI2kKxZgN-0-a6b95890ce4499e0314c8bd1803ed871)
2.8.2 Egret的触摸事件
触摸事件处理是移动游戏开发中常见的交互方式,Egret的触摸事件处理方式也是基于上一节介绍的事件处理机制的。其对应的事件类是egret.TouchEvent,它包含以下事件类型:
● TOUCH_BEGIN:当用户第一次触摸启用触摸的设备时触发。
● TOUCH_CANCEL:由于某个事件取消了触摸时触发。
● TOUCH_END:当用户移除与启用触摸的设备的接触时触发。
● TOUCH_MOVE:当用户触碰设备并移动时进行触发,而且会连续触发,直到接触点被删除。
● TOUCH_TAP:当用户在触摸设备上与开始触摸的同一 DisplayObject实例上抬起接触点时触发。
下面通过代码来说明它们的使用方式,创建一个称为“TouchEvent”的项目,删除src文件夹内的所有文件,创建一个称为Main.ts的类文件,并做出如下修改,参见二维码2-31:
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/56_04.jpg?sign=1739523325-r5NDMF7BKCCe9yS2Re7v9j3ahm50y2GJ-0-ebeb5f48f73dcd6c667e4fafd286ecfc)
二维码2-31
运行调试播放器观看效果,如图2-52所示:
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/56_05.jpg?sign=1739523325-FfqQMoS56XtwfzkdmAc79O59kVrYoUxB-0-4a08485763684741ff408b450ced825c)
图2-52 程序运行结果
当单击绿色矩形的时候,调试窗口会输出如图2-53所示的内容:
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/57_01.jpg?sign=1739523325-DLrxYB7T87MEpg7r6zPtk6bhyFqH8Ccl-0-42f197059515afa789066ea9e421b084)
图2-53 程序控制台输出
在代码的第16行,向矩形对象注册了触摸事件监听器——onRectTouch方法,当矩形对象被单击的时候就会调用这个方法。
在代码的第17行,向矩形对象的容器注册了触摸事件监听器——onContainerTouch方法,因为容器的大小默认情况下是由子节点的大小决定的,所以当矩形对象被单击时,同样也会让容器触发触摸事件。
在代码的第18行,向容器对象注册了触摸事件监听器——onTouchCaptured 方法,当矩形对象的触摸事件发生时,该事件会向上冒泡,找到矩形对象所在的容器之后,执行了这个方法。
如果把第15行代码的true改为false,那么触发事件就不会发生了,有兴趣的读者可以去试试。