【问题标题】:Waiting for animations in a SetInterval gameloop在 SetInterval 游戏循环中等待动画
【发布时间】:2014-02-05 02:27:35
【问题描述】:

所以我的问题是我想插入一个自定义动画,但我不想破坏我的游戏循环。

我的初始游戏循环在这里说明:

function init(){

      if(!gameOver){
        if(resetInterval>-1) clearInterval(resetInterval);
        createBlock();
        resetInterval = setInterval(moveDownCheck,gameSpeed);
      }
    }

我的游戏是一个类似俄罗斯方块的游戏,只是我没有掉落俄罗斯方块,而是掉落 2x1 不同颜色的方块。 moveDownCheck 方法检查我的 2x1 块下是否有任何块,然后将其删除 1 行。由于 2x1 块已连接,因此这工作正常,直到我有一个块在下面没有块的情况下悬挂。我想插入一个大约需要一秒钟的放置动画,并以相同的gameSpeed 增量放置悬挂块。 这是我失败的尝试:

function moveFallingDown(){
      fbDownFlag = false;
      clearInterval(resetInterval);
      fbInterval = setInterval(function(){
        fallingBlock.row++;
        console.log("Dropped One Row");
        },gameSpeed);
      while(landscape[fallingBlock.row+1][fallingBlock.col]==0){
        console.log("Waiting to Drop Falling Block");
      }
      clearInterval(fbInterval);
      resetInterval = setInterval(moveDownCheck,gameSpeed);
}

我在这里尝试等待function(){fallingBlock.row++;},但我的游戏崩溃了,在控制台中"Dropped One Row" 而"Waiting to Drop Falling Block" 将显示数千次。 我想我不应该在这里使用 while 循环,但我能想到的唯一其他解决方案是对我的设计进行彻底的返工,或者嵌套 setInterval 方法,这会让我的头疼得厉害。

【问题讨论】:

    标签: javascript setinterval


    【解决方案1】:

    你不能用 while 循环来做到这一点,你需要使用递归函数。 window.setTimeout 可以工作,但这似乎是 requestAnimationFrame 的一个很好的用例。在这里查看:https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame

    您可以使用它来调用您的 moveFallingDown 方法,并使用传递给 requestAnimationFrame 回调的高精度时间戳检查自上一个动画帧以来经过了多长时间,以根据游戏速度将动画移动正确的量.

    【讨论】:

    • 感谢您帮助我解决 Adrien,但我对这将如何帮助我感到有些困惑。 requestAnimationFrame 是否等到回调函数完成后再继续?
    • requestAnimationFrame 会在每次浏览器重新绘制屏幕时调用您的回调函数,大约每秒发生 60 次。它会向您的函数传递一个高分辨率时间戳,说明重绘的确切时间。因此回调函数可以使用该时间戳来确定自上次调用以来已经过去了多少时间,并根据差异确定动画的时间。然后它应该决定是否再次调用requestAnimationFrame 以保持进程继续进行。
    【解决方案2】:

    @Adrien Delessert 的建议是正确的,但我只想补充一点,您肯定会混淆 setTimeout 和 setInterval。

    首先,您不需要 while 循环。

    setInterval 是一个循环。因此,如果您想使用它,您需要(基本上)将整个游戏包装在一个可以推动游戏前进的方法中(无论这意味着什么)并将其传递给 setInterval。

    但是,您正在做的(这实际上不是一个糟糕的方法)是将其用作动画特定事物的一种手段。在这种情况下,如果满足另一轮动画的条件,您应该有一个递归(ish)函数,它在完成时继续调用 setTimeout。

    我从未使用过 requestAnimationFrame,但这听起来确实是解决问题的一种更优雅的方法。

    它更好的原因是它利用了浏览器自己的刷新计时器(大约每秒 60 次),并将你的动画帧与它自己的刷新一起插入。

    所以是的,您将监听该回调,然后根据需要对其做出反应。如果每秒 60 倍的速度太快,您需要输入一个基于 % 的计数器来计算您希望实际响应的帧数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-26
      • 1970-01-01
      • 1970-01-01
      • 2021-08-29
      • 1970-01-01
      • 2012-08-02
      • 2014-01-21
      相关资源
      最近更新 更多