游戏循环机制

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" 时间放缓实现的,但这也是可以定制的。参见方法文档的详细描述!