您使用 requestAnimationFrame (RAF) 吗? RAF 将进行垂直同步,但 setTimeout/setInterval 不会。
http://msdn.microsoft.com/library/windows/apps/hh920765 http://msdn.microsoft.com/library/windows/apps/hh920765
另外,由于 30fps 足以让用户看到流畅的运动,因此将 60fps 分成 2 个交替部分怎么样:
一帧期间“计算/更新”(无绘图)
然后在下一帧中完成所有绘图。
并且,了解 Chrome 的时间轴工具。这个很棒的小工具可以让您分析代码以发现代码在哪里花费了最多的时间。然后重构这部分代码以获得高性能。
[添加:有关 requestAnimationFrame 的更多有用细节]
画布不会直接在显示屏上绘制。相反,画布“渲染”到临时的屏幕外缓冲区。 “渲染”是指执行canvas命令在离屏缓冲区上进行绘制的过程。当下一次屏幕刷新发生时,该离屏缓冲区将快速绘制到实际显示屏幕。
当刷新期间在实际显示屏幕上绘制离屏缓冲区时,当离屏渲染过程仅部分完成时,就会发生撕裂。
setInterval 不会尝试协调渲染与屏幕刷新。所以,使用setInterval来控制动画帧偶尔会产生撕裂现象。
requestAnimationFrame (RAF) 尝试通过仅在屏幕刷新之间生成帧(称为垂直同步的过程)来修复撕裂问题。典型的显示屏每秒刷新大约 60 次(即每 16 毫秒)。
使用 requestAnimationFrame (RAF):
如果当前帧在下一次刷新之前没有完全渲染,
RAF 会延迟当前帧的绘制,直到下一次屏幕刷新。
这种延迟减少了撕裂。
所以对你来说,RAF 可能会帮助你解决撕裂问题,但它也会带来另一个问题。
您必须决定如何处理物理处理:
- 将其保留在单独的进程中,例如 setInterval。
- 将其移至 requestAnimationFrame 中。
- 将其移至 web-workers(工作是在与 UI 线程分开的后台线程上完成的)。
将物理保持在单独的 setInterval 中。
这有点像乘坐两列火车,每列一条腿——非常困难!您必须确保物理的所有方面始终处于有效状态,因为您永远不知道 RAF 何时会读取物理进行渲染。您可能必须创建物理变量的“缓冲区”,以便它们始终处于有效状态。
将物理转移到 RAF:
如果您可以在刷新之间的 16 毫秒内计算物理和渲染,那么此解决方案是理想的。如果没有,您的帧可能会延迟到下一个刷新周期。结果是 30fps,这并不可怕,因为眼睛在 30fps 时仍然可以感知清晰的运动。最坏的情况是有时会出现延迟,有时不会,那么您的动画可能会显得不稳定。因此,这里的关键是在刷新周期之间尽可能均匀地分布计算。
将物理转移到网络工作者中
JavaScript 是单线程的。 UI 和计算都必须在这个单线程上运行。但是您可以使用在单独线程上运行物理的网络工作线程。这可以释放 UI 线程,让其专注于渲染和绘画。但您必须协调背景物理与前台 UI。
祝你游戏顺利:)