游戏循环机制
Crafty 的游戏循环使用 Crafty.timer.step 实现。它使用全局事件与引擎的其余部分进行通信。如果可用,底层的游戏循环使用 requestAnimationFrame
, 包括以下几个阶段:
- 一次或多次的调用 "EnterFrame" 来推进游戏状态。
- 调用 "RenderScene" 渲染每一个层。
一切都由 "EnterFrame" 解决之前的场景渲染,例如,如果你移动一个对象好几次在一个单一的事件,只有最后的位置将是可见的。
还有一些用于基准测试和细粒度控制的其他事件,但以上两个事件是最重要的。
EnterFrame
绑定到该事件的函数通过一个具有几个属性的对象传递,其中只有几个属性是非常重要的:
data = {
frame: frameNumber // the number of frames since Crafty.init()
dt: ms // the time in ms which has passed since the last "EnterFrame" event
}
所有的游戏逻辑,即任何随时间的变化,最终挂载到 "EnterFrame" 事件。为了简化这种交互,存在许多组件(如 "Tween" ),但为了提供自定义行为,您可能最终将实体直接绑定到该事件。如果你想提供平滑的行为,你应该使用 dt
属性来决定游戏状态应该前进多远。举个简单的例子,这里有一个红色方块,它将以每秒10像素的速度移动到右边:
Crafty.init(400, 400);
var square = Crafty.e('2D, Canvas, Color');
.attr({x: 10, y: 10, w: 100, h: 100})
.color('red')
.bind("EnterFrame", function(eventData) {
// Move to the right by 10 pixels per second
this.x = this.x + 10 * (eventData.dt / 1000);
};
RenderScene
渲染成像 "Canvas" 和 "DOM" 都会监听这个事件来确保你看到游戏进行的状态。最为最终的 "EnterFrame" 事件,除非你实现自定义的渲染层,否则永远不需要绑定到这个事件。
Crafty.timer.steptype
Crafty.timer.steptype 函数可以让你控制 "EnterFrame" 消耗的时间。这是一个非常复杂的课题;要深入的讨论, 参见 Glenn Fiedler 的 Fix Your Timestep 一文。
Crafty 有一个默认固定的时间单位,它是通过多次 "EnterFrame" 时间放缓实现的,但这也是可以定制的。参见方法文档的详细描述!