如何同步运行requestAnimationFrame()?

Tao*_*que 0 javascript requestanimationframe

因此,我正在制作像游戏这样的小俄罗斯方块,其中瓷砖彼此之间掉落,被破坏等。我正在通过制作HTML5画布动画requestAnimationFrame()。调用此方法可收集悬挂在空中的瓷砖并将其平稳地放下:

function dropTiles() {
    var tileArray = getFallingTiles();
    function step() {
        var finished = true;
        for (var index = 0; index < tileArray.length; ++index) {
            var currentTile = tileArray[index];
            if (currentTile.fallDepth > 0) {
                finished = false;
                currentTile.erase();
                currentTile.positionY -= 1;
                currentTile.fallDepth -= 1;
                currentTile.draw();
            }
        }
        if (!finished) {
            window.requestAnimationFrame(step);
        }
    }
    window.requestAnimationFrame(step);
}
Run Code Online (Sandbox Code Playgroud)

这是从以下位置调用上述方法的主要方法:

function doGameEvents() {
    setCanvasListeners(false);
    do {
        var comboFactor = 1;
        dropTiles();
        while (getGroups()) {
            score();
            dropTiles();
            ++comboFactor;
        }
        if (comboFactor == 1) {
            var newTile = getRandomTile();
            TILES.push(newTile);
            dropTiles();
        }
    } while (!hasMoves());
    setCanvasListeners(true);
}
Run Code Online (Sandbox Code Playgroud)

一切正常,但是我注意到,一旦dropTiles()调用该控件,就立即将其转移到下一条指令,即使该指令尚未完成(即score(),调用仍在空中悬挂瓷砖)。

所以我的问题是:如何requestAnimationFrame()在控件退出我的dropTiles()方法之前使同步并完全完成?

spe*_*der 5

你不知道 您重写您的放置方法,以在完成时通知您。最简单的说:

function dropTiles(callback) {
    //...
    function step() {
        //...
        if (!finished) {
            window.requestAnimationFrame(step);
        }
        else
        {
            if(callback)callback();
        }
    }
    window.requestAnimationFrame(step);
}
Run Code Online (Sandbox Code Playgroud)

所以现在当您打电话时drop,您可以

drop(function(){
    //this code runs when drop is finished
});
Run Code Online (Sandbox Code Playgroud)

如果您需要等待很多drops完成,则可以选择使用Promises。(提示:承诺将继续存在……您应该真正学习如何使用它们)。

function dropTiles() {
    return new Promise(function(resolve,reject){
        //...
        function step() {
            //...
            if (!finished) {
                window.requestAnimationFrame(step);
            }
            else
            {
                resolve();
            }
        }
        window.requestAnimationFrame(step);
    });
}
Run Code Online (Sandbox Code Playgroud)

现在你可以:

drop().then(function(){
    //drop is finished
});
Run Code Online (Sandbox Code Playgroud)

要么

Promise.all([drop(), drop(), drop()]).then(function(){
    //all the drops finished
});
Run Code Online (Sandbox Code Playgroud)