-
Notifications
You must be signed in to change notification settings - Fork 385
MailBox
信箱 (mailbox) 是 ECS 的一部分,它是对 ecs 基础功能的一个补充。
在开发 Ant 的过程中,我们发现只有 System 和 Component 不能满足所有的需要。数据如果只存在于 component 中,有些信息用 component 传递很不方便。所以,我们增加了消息和信箱的概念。
一条消息是由多个 lua 值构成的 lua 数组组成,第一个值通常是字符串。
world:pub { "message_name", ... }
这样就可以广播一条消息,消息的第一个值约定用来区分消息类型,它是一个表示消息是什么的字符串。
在同一个 Lua 虚拟机内,只有可以访问 world 对象,就可以通过订阅消息创建出一个信箱:
local mb = world:sub { "message_name" }
这样就构造了一个信箱,所有第一个值为 "message_name" 的消息都会发到这个信箱内。信箱也可以匹配不止一个 Lua 值。
消息是广播的。所以,你可以为相同的消息前缀创建多个信箱,每个信箱都会收到相同的消息。消息只会投递到 pub 消息那一刻之前创建出来的信箱中。如果你先 pub 了一条消息,之后才创建可以截获这条消息的信箱,那么该信箱是不会收到这条消息的。
如果消息在广播那一刻没有发现有任何信箱会收到消息,该消息就立刻被销毁。
信箱可以通过 world:unsub()
销毁。
如果消息中包含的 Lua 值需要在消息被销毁时做一些回收工作,固然,你可以给这些值加上 gc 方法,但更好的方法是给消息加一个 .close 函数。消息被销毁时会主动调用它,这个函数比Lua 的 gc 方法调用更即时。
你可以在 ecs 系统中找到一个合适的 stage 实现一个消息处理函数。使用 for _, message, args in mailbox:unpack()
就可以将信箱中的消息逐条取出。
Ant 引擎会将交互消息,如鼠标、键盘、手势等消息以系统消息的形式广播出去。如果你的游戏需要处理这些消息,创建信箱捕获它们,并在合适的 stage 里遍历信箱处理这些消息。注意:和许多其它游戏引擎不同,这些交互事件并不是通过 callback 函数实现的,而是通过信箱。如果你不创建对应的信箱,消息就会被抛弃掉;引擎也没有指定特定的 stage 处理它们,你可以在你喜欢的任何 stage 处理这些消息。和 callback 机制不同,pipeline + stage 的机制可以让你明确这些交互消息处理的时机,而 callback 机制下,你并不知道回调函数发生在什么时候。
例如,如果你想捕获键盘消息,在系统的初始化阶段创建一个信箱:
local kb_mb = world:sub {"keyboard"}
在合适的 stage 中,遍历这个信箱:
for _, key, press, state in kb_mb:unpack() do
on_key(key, press)
end
这样你就模拟了 on_key
这个回调函数。
以下列出了用户会关心的大部分现有的系统消息。这个文档很可能过时,建议写一些实现的代码测试这些消息以了解消息的具体含义。
- type : "keyborad"
- press : true / false 按下或抬起。
- state : 系统给出的数字状态值,包含有 ctrl shift 等按键的状态。
- type : "mouse"
- button : "LEFT" / "RIGHT" / "MIDDLE"
- action : "MOVE" / "DOWN" / "UP"
- x : X 坐标
- y : Y 坐标
- type : "touch"
- x : X 坐标
- y : Y 坐标
- touchid
- state
- type : "gesture"
- what : "tap" / "pinch" / "longpress" / "pan" / "swipe"
- 根据不同手势,有不同的参数
- type : "size"
- width : 窗口改变大小后的宽度
- height : 窗口改变大小后的高度
- type : "dropfiles"
- filename : 从外部拖拽进窗口的文件名,供编辑器使用。