0

这可能是一个愚蠢的/以前回答过的问题,但它一直困扰着我和我的朋友一段时间,我一直无法找到一个好的答案。

现在,我让我所有的 JS Canvas 游戏都在滴答声中运行。例如:

function tick(){
//calculate character position
//clear canvas
//draw sprites to canvas
if(gameOn == true)
    t = setTimeout(tick(), timeout)
}

这适用于高端系统上的 CPU 低级游戏,但是当我尝试在每个刻度上多画一点时,它开始以慢动作运行。所以我的问题是,如何在允许可变帧速率的同时保持 x、y 位置和命中检测计算全速进行?

旁注:我曾尝试使用 requestAnimationFrame API,但老实说,它有点令人困惑(不是所有关于它的好教程),虽然它可能会加快您的处理速度,但它并不能完全解决问题。

谢谢大家 - 任何帮助表示赞赏。

4

3 回答 3

0

正如科林克所说。setTimeout看起来像一个错误。假设这只是一个错字而不是真正的错误,我会说它不太可能是动画本身(也就是说,DOM 更新)真正减慢了你的代码。

多一点是多少?我在 1.2GHz Atom 上网本上的 VMWare 中的 IE7 上一次在屏幕上动画了数百个元素(我在最慢的机器上拥有最慢的浏览器,VMWare 是因为我使用 Linux)。

以我的经验,如果未正确完成命中检测,当您制作动画的元素数量增加时,会导致最慢的速度。这是因为一个简单的实现本质上是指数级的(它会尝试进行n^n比较)。解决这个问题的方法是过滤掉比较以避免不必要的比较。

在游戏引擎中执行此操作的最常见方法之一(无论语言如何)是将您的世界地图分割成一组更大的网格。然后,您只需对同一网格中的项目进行命中检测(如果您想要更准确,还可以检测相邻的网格)。这大大减少了您需要进行的比较次数,尤其是在您有很多字符的情况下。

于 2013-03-07T02:57:11.973 回答
0

RequestAnimationFrame 有很大的不同。这可能是您问题的解决方案。您还可以做两件事:设置第二个刻度系统来处理它的模型方面,例如命中检测。一个很好的例子是 PhysiJS 是如何做到的。它更进一步,并使用了一些新浏览器的一项功能,称为网络工作者。它允许您使用第二个 CPU 内核。John Resig 有一个很好的教程。但请注意,它很复杂,没有得到很好的支持(因此有问题,它往往会崩溃很多)。

真的,请求动画帧很简单,只要几行,一旦你设置了你就可以忘记它。它不应该更改您现有的任何代码。理解代码的作用有点挑战,但您几乎可以为那里的示例剪切和替换您的 setTimeout 代码。如果你问我,setTimeout 也一样复杂!它们几乎做同样的事情,除了 setTimeout 有延迟时间,而 requestAnimationFrame 没有 - 它只是在准备好时调用您的函数,而不是在设定的时间段之后。

于 2013-03-07T01:22:37.933 回答
0

您实际上并没有使用刻度线。正在发生的事情是你一遍又一遍地反复打电话tick()。您需要删除()并离开 就setTimeout(tick,timeout);我个人而言,我喜欢用它arguments.callee来明确声明一个函数调用自己(从而消除知道函数名的依赖性)。

话虽如此,我在实现可变帧速率时喜欢做的是尽可能地简化底层引擎。例如,为了让一个球在墙上反弹,我检查从球的前一个位置到下一个位置的线是否撞到墙上,如果是,什么时候撞到。

话虽如此,您需要小心,因为某些浏览器会在打开 contaxt 菜单(或任何其他菜单)时停止所有 JavaScript 执行,因此您最终可能会在两个“帧”之间出现几秒钟甚至几分钟的间隙。我个人认为在大多数情况下,基于帧的计时是要走的路。

于 2013-03-07T01:30:34.167 回答