javascript中的超时与setTimeout不一致?
我在做游戏。游戏有1个主循环:javascript中的超时与setTimeout不一致?,javascript,html,canvas,Javascript,Html,Canvas,我在做游戏。游戏有1个主循环: //draws a new frame and game logic function draw() { player.gameTick(); game.gameTick(); lastTime=newTime; background.draw(ctx); player.draw(ctx); enemies.draw(ctx); setTimeout(draw,50); } 正常情况下,这运行良好,我得到20 fp
//draws a new frame and game logic
function draw()
{
player.gameTick();
game.gameTick();
lastTime=newTime;
background.draw(ctx);
player.draw(ctx);
enemies.draw(ctx);
setTimeout(draw,50);
}
正常情况下,这运行良好,我得到20 fps报告给#控制台。然而,偶尔fps峰值会超过125。(表示在上次调用后不到50毫秒调用draw)。当这种情况发生时,游戏开始延迟几秒钟,然后fps返回。(这也是违反直觉的,为什么较高的fps会导致滞后?)
不管怎样,有人知道为什么会这样吗
是的,我也尝试过setInterval(),同样的情况也发生了=/ JavaScript是单线程的。如果您单独安排两次50毫秒的超时,则它们有可能最终发生碰撞或接近碰撞,并导致一秒钟的奇怪处理阻塞,然后才能自行清理并再次腾出空间。您可能应该合并代码并创建一个调用其他两个函数的主循环。这样,您可以确保它们每50毫秒处理一次 您的流程如下所示:
function mainLoop() {
player.tick();
game.tick();
background.draw();
players.draw();
enemies.draw();
setTimeout(mainLoop, 50);
}
mainLoop()
function mainLoop() {
player.tick();
game.tick();
background.draw();
players.draw();
enemies.draw();
setTimeout(mainLoop, 50);
}
mainLoop()
请注意,没有重复的setTimeout调用。一切都可以一下子发生。您正在演示的代码的两个版本中创建冲突。此问题是由浏览器javascript计时器节流引起的。我注意到,当我打开许多选项卡或在选项卡之间切换时,问题变得更严重。Chrome没有那么大的问题,很可能是因为标签处于独立的进程中
Firefox7似乎已经为FF解决了这个问题 所以首先,你知道你不能保证两个请求之间有50毫秒的间隔,对吗?好吧,跳过我说的要阻止更多评论的那一点,在125+fps之前会发生什么?另外,您将
lastTime
设置在何处?有点离题,但如果您实际在draw
函数中运行$(“#console”)
,请将其缓存在函数外部。每秒执行20次相同的DOM选择是很不幸的。@patrickdw,是的,但是在没有执行DOM选择和写入的情况下,显示了相同的行为=/在jcolebrand的评论之后,您会想知道setTimeout中指定的函数将在50毫秒后添加到调用堆栈中。它只会在堆栈最终到达该函数时执行。见Jon Resig关于这个主题的文章:这实际上是我最初的做法。我有一个处理重画和逻辑的循环。同样的问题也发生了。对,我理解碰撞的问题。我将把两个循环折叠成一个。但问题是,我本来就是这样做的。当这两个是1循环时,发生了完全相同的问题。是什么原因造成的?@razorstrom-我还不能100%保证这一点。我需要更多地了解您的代码以及它是如何设置的。正如jcolebrand所问的,fps“spike”之前会发生什么?><这是一个编辑错误。这里应该只有一个setTimeout调用,哈哈哈。至于在经济放缓之前发生了什么,这似乎没什么。这几乎是随机发生的。然而,在切换到另一个选项卡并返回后(在firefox6中),这种情况会发生得更多。所以我假设这与浏览器节流有关。