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