![游戏开发实战宝典](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=1738851444-9utLZnNi1yU1MkehQm8eJGRQC59bZkWA-0-2a65be554bb4a570420c6f8b5b92b67c)
NewsEvent就是一个事件类,其中的content字段就是事件携带的数据。egret.Event类的构造函数的原型如下:
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/55_02.jpg?sign=1738851444-eqenN53ibVtMwDMEcRmTSW9L8cMFhU3u-0-c983078d571651fa338f9a40d3bba4d0)
以下是对各个参数的解释:
● 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=1738851444-RKcPRbd6waJXba31ZK84FBk4YOeHZ2xL-0-01e7e20228db97d7715f7fb451cb78e8)
二维码2-28
NewsDispatcher类就是事件发布者类,类似新闻发布机构。
接下来创建一个称为NewsReader的类文件,参见二维码2-29:
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/55_04.jpg?sign=1738851444-KlgMj6ynIqNVFoqnB7WgiB6cPrqbg4Vw-0-06048dfa6a7b17208e08f16741f1f0f4)
二维码2-29
NewsReader类就是事件监听者类。接下来看一下以上三个类如何协同工作。首先创建一个称为Main的类文件如下,参见二维码2-30:
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/55_05.jpg?sign=1738851444-aVzNYAAqN5rDR6ctqEey9SopvPappw0g-0-ded404f87aad3a032fc138e1e8d18e56)
二维码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=1738851444-5QX65KZfpJb3Sg5pYhpZRvMqCaw1stfl-0-025791d645d38a7175e6c4b742dee072)
图2-51 程序控制台输出
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/55_07.jpg?sign=1738851444-IlfsFFBOn3hpA2g7H4tkTsJ3mB265zxj-0-eab630728616fee0ff44413c2d16d661)
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/56_01.jpg?sign=1738851444-oaXJlEtyXYBQV3bkbbJaEl07NXE5E724-0-6b1d715ebb5374f971f0bc42470b99c1)
以下是对各个参数的解释:
● 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=1738851444-PydM0ncgs5A48FVeIqQkGTbB6PDTctEH-0-2a15c81f4a38e1089364460d63240f14)
以及是否含有监听器:
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/56_03.jpg?sign=1738851444-1TNlU2UzGhnctjhINJUu7NjY9JXo1g0h-0-e8e7ab13939838edb7d92b103a1801ad)
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=1738851444-Cef539BnxVp7XVe77KzLR1WdFhjDcYS0-0-69ee4e60b67452eb3d4d76fdabf0df4b)
二维码2-31
运行调试播放器观看效果,如图2-52所示:
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/56_05.jpg?sign=1738851444-yNfwSCSXoHHnKPb6SK1Agw2rcK4jPDLZ-0-2cab53ead2314cebe9f0395078602f0b)
图2-52 程序运行结果
当单击绿色矩形的时候,调试窗口会输出如图2-53所示的内容:
![](https://epubservercos.yuewen.com/190630/23446275309889706/epubprivate/OEBPS/Images/57_01.jpg?sign=1738851444-U9Op7ArMqRgdtbuMvSaa9qYq3JYx1WcO-0-53a3f03025bca2f210126bf1ed25ff0e)
图2-53 程序控制台输出
在代码的第16行,向矩形对象注册了触摸事件监听器——onRectTouch方法,当矩形对象被单击的时候就会调用这个方法。
在代码的第17行,向矩形对象的容器注册了触摸事件监听器——onContainerTouch方法,因为容器的大小默认情况下是由子节点的大小决定的,所以当矩形对象被单击时,同样也会让容器触发触摸事件。
在代码的第18行,向容器对象注册了触摸事件监听器——onTouchCaptured 方法,当矩形对象的触摸事件发生时,该事件会向上冒泡,找到矩形对象所在的容器之后,执行了这个方法。
如果把第15行代码的true改为false,那么触发事件就不会发生了,有兴趣的读者可以去试试。