Egret Note
Egret Engine 的学习笔记。
Egret Engine 是一款基于 JavaScript 的游戏制作引擎,支持 2D 与 3D 模式,支持 Canvas 与 WebGL 渲染,目前使用 TypeScript 编写。
显示对象
“显示对象”,准确的含义是可以在舞台上显示的对象。可以显示的对象,既包括可以直接看见的图形、文字、视频、图片等,也包括不能看见但真实存在的显示对象容器。
在Egret中,视觉图形都是由显示对象和显示对象容器组成的。
对象树
- 根:舞台
DisplayObjectContainer:Stage
- 茎:主容器(文档类)
DisplayObjectContainer
- 树枝:容器
DisplayObjectContainer
- 树叶:显示对象
DisplayObject
对象类型
DisplayObject
显示对象基类,所有显示对象均继承自此类Bitmap
位图,用来显示图片Shape
用来显示矢量图,可以使用其中的方法绘制矢量图形TextField
文本类BitmapText
位图文本类DisplayObjectContainer
显示对象容器接口,所有显示对象容器均实现此接口Sprite
带有矢量绘制功能的显示容器Stage
舞台类
基本概念
二维坐标系。原点位于左上角。
var shape:egret.Shape = new egret.Shape(); |
支持的操作:
- alpha:透明度
- width:宽度
- height:高度
- rotation:旋转角度
- scaleX:横向缩放
- scaleY:纵向缩放
- skewX:横向斜切
- skewY:纵向斜切
- visible:是否可见
- x:X 轴坐标值
- y:Y 轴坐标值
- anchorOffsetX:对象绝对锚点 X
- anchorOffsetY:对象绝对锚点 Y
锚点
Display Object 显示在舞台上的的位置需要通过 Anchor 来计算(初始值位于 Display Object 的左上角),可以通过 anchorOffsetX
和 anchorOffsetY
方法来改变对象的锚点(比如移至中点)。
定位
Display Object 的初始坐标为 (0, 0),即位于容器的左上角(而非舞台)。
- 相对于容器的位置可以类比作
position: relative
- 相对于舞台的位置可以类比作
position: absolute
如果要获取绝对位置,需要调用 container.globalToLocal(x, y)
方法,参数代表舞台坐标,返回值为容器坐标。
至于 z-index
则跟 svg 的处理类似。
尺寸
两种方法更改尺寸:
- height / width
- scaleX / scaleY
斜切
斜切可以造成类似矩形变形为平行四边形的效果。
- skewX:横向斜切
- skewY:纵向斜切
对象容器
DisplayObjectContainer
是 DisplayObject
的子类。
向 Container 中添加 DisplayObject:
container.addChild(displayObject); |
同一个显示对象无论被代码加入显示列表多少次,在屏幕上只绘制一次。如果一个显示对象 A 被添加到了 B 这个容器中,然后 A 又被添加到了 C 容器中。那么在第二次执行 C.addChild(A) 的时候,A 自动的从 B 容器中被删除,然后添加到 C 容器中。
移除:
container.removeChild(displayObject); |
深度管理
DisplayObject 的 z-index
由其插入到容器中的顺序决定。后插入的显示在上层。
插入到指定位置使用 container.addChildAt(object, index)
方法。
同时也有 container.removeChileAt(index)
方法。
删除全部对象使用 container.removeChildren()
方法。
交换 DisplayObject 的位置有两个方法:
container.swapChildren(object, object)
container.swapChildrenAt(index, index)
手动设置 z-index 使用 container.setChildIndex( object, index )
方法。
子对象选择
通过 z-index 获取:container.getChildAt(index)
通过 name 获取(需要预先给 DisplayObject 设置 name 属性):container.getChildByName(name)
通过 z-index 获取子对象性能更佳。
矢量绘图
Egret中可以直接使用程序来绘制一些简单的图形,这些图形在运行时都会进行实时绘图。要进行绘图操作,我们需要使用 Graphics 这个类。但并非直接使用。 一些显示对象中已经包含了绘图方法,我们可以直接调用这些方法来进行绘图。 Graphics 中提供多种绘图方法。
已有的绘图方法包括:矩形、圆形、直线、曲线、圆弧。
以下的 shp
代表 shape,即一个 Shape 对象的实例。
shp.graphics.clear()
是通用的清楚绘图方法。
基本图形
矩形
var shp:egret.Shape = new egret.Shape(); |
圆形
shp.graphics.lineStyle( 10, 0x00ff00 ); |
此处需要注意的是,圆形的X轴和Y轴位置是相对于Shape对象的锚点计算的。
直线
shp.graphics.lineStyle( 2, 0x00ff00 ); |
曲线
shp.graphics.lineStyle( 2, 0x00ff00 ); |
圆弧
drawArc( x:number, y:number, radius:number, startAngle:number, endAngle:number, anticlockwise:boolean ):void |
前面的参数跟前面绘制圆形的一样,圆弧路径的圆心在 (x, y) 位置,半径为 radius 。后面的参数表示根据 anticlockwise : 如果为 true,逆时针绘制圆弧,反之,顺时针绘制。
需要注意是传入的 startAngle 和 endAngle 均为弧度而不是角度。
遮罩
DisplayObject 有一个 mask
属性,简单来说,就是类似蒙版上面的一个洞。但这个 mask
是洞而不是蒙版。如果添加了 mask
属性,则 Object 只能显示这个“洞中”的内容。
用作遮罩的显示对象可设置动画、动态调整大小。遮罩显示对象不一定需要添加到显示列表中。但是,如果希望在缩放舞台时也缩放遮罩对象,或者如果希望支持用户与遮罩对象的交互(如调整大小),则必须将遮罩对象添加到显示列表中。
不能使用一个遮罩对象来遮罩另一个遮罩对象。
通过将 mask 属性设置为 null 可以删除遮罩。
mySprite.mask = null; |
碰撞检测
- 非精确:
var isHit:boolean = shp.hitTestPoint( 10, 10 );
- 精确:
shp.hitTestPoint( 10, 10,ture);
非精确大概可以看做面积相交,精确则是边缘相交。
大量使用精确碰撞检测,会消耗更多的性能。
文本
Egret 提供三种不同的文本类型,不同类型具有以下特点:
- 普通文本:用于显示标准文本内容的文本类型
- 输入文本:允许用户输入的文本类型
- 位图文本:借助位图字体渲染的文本类型
样式
var label:egret.TextField = new egret.TextField(); |
支持格式混排:
// JSON 模式 |
事件与链接
tx.textFlow = new Array<egret.ITextElement>( |
也可以直接将 href
设置为 url,这样不需要事件监听,将直接打开链接。但只适用 Web 端。
文本输入
关键代码是设置其类型为 INPUT。
var txInput:egret.TextField = new egret.TextField; |
绘制输入背景可以用其它 DisplayObject,目前没有内置实现。
获取焦点使用 textIput.setFocus();
方法。
除此以外,还有 inputType
属性表示输入内容的区别,这个主要用于移动端弹出相应的键盘。
事件处理
事件类:egret.Event
执行流程
事件机制包含4个步骤:注册侦听器,发送事件,侦听事件,移除侦听器。这四个步骤是按照顺序来执行的。
事件类
其构建器可以传 3 个参数:事件类型、是否冒泡、是否可取消(什么是取消?)。
class DateEvent extends egret.Event |
监听器
跟常见的情况不太一样,Egret 的事件绑定在发送者上(而不是接收者)。
监听器函数
一个侦听器必须是函数,它可以是一个独立函数,也可以是一个实例的方法。侦听器必须有一个参数,并且这个参数必须是 Event 类实例或其子类的实例, 同时,侦听器的返回值必须为空(void)。
注册与移除事件监听
注册侦听器
eventDispatcher.addEventListener(eventType, listenerFunction, this); |
移除侦听器
eventDispatcher.removeEventListener(eventType, listenerFunction, this); |
检测侦听器
eventDispatcher.hasEventListener(eventType); |
优先级
public addEventListener(type:string, listener:Function, thisObject:any, useCapture:boolean = false, priority:number = 0) |
该属性为一个number类型,当数字越大,则优先级越大。在触发事件的时候优先级越高。