javascript - How to run requestAnimationFrame() synchronously? - Stack Overflow

So I'm making a small tetris like game where tiles fall on each other, get destroyed etc. I'm

So I'm making a small tetris like game where tiles fall on each other, get destroyed etc. I'm making HTML5 canvas animation through requestAnimationFrame(). This method is called to gather tiles hanging in mid-air and drop them down smoothly:

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);
}

This is the main method where the above method is called from:

function doGameEvents() {
    setCanvasListeners(false);
    do {
        var boFactor = 1;
        dropTiles();
        while (getGroups()) {
            score();
            dropTiles();
            ++boFactor;
        }
        if (boFactor == 1) {
            var newTile = getRandomTile();
            TILES.push(newTile);
            dropTiles();
        }
    } while (!hasMoves());
    setCanvasListeners(true);
}

Everything works okay but I noticed that once dropTiles() is called the control gets immediately transferred to the next instruction, even if the latter is not yet finished (i.e. score() is called with tiles still hanging in mid-air).

So my question is: how to make requestAnimationFrame() synchronous and pletely finish before the control exits my dropTiles() method?

So I'm making a small tetris like game where tiles fall on each other, get destroyed etc. I'm making HTML5 canvas animation through requestAnimationFrame(). This method is called to gather tiles hanging in mid-air and drop them down smoothly:

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);
}

This is the main method where the above method is called from:

function doGameEvents() {
    setCanvasListeners(false);
    do {
        var boFactor = 1;
        dropTiles();
        while (getGroups()) {
            score();
            dropTiles();
            ++boFactor;
        }
        if (boFactor == 1) {
            var newTile = getRandomTile();
            TILES.push(newTile);
            dropTiles();
        }
    } while (!hasMoves());
    setCanvasListeners(true);
}

Everything works okay but I noticed that once dropTiles() is called the control gets immediately transferred to the next instruction, even if the latter is not yet finished (i.e. score() is called with tiles still hanging in mid-air).

So my question is: how to make requestAnimationFrame() synchronous and pletely finish before the control exits my dropTiles() method?

Share Improve this question asked Oct 21, 2015 at 12:26 ttaaoossuuttaaoossuu 7,8943 gold badges32 silver badges60 bronze badges 0
Add a ment  | 

1 Answer 1

Reset to default 8

You don't. You rewrite your drop method to notify you when it is done. At its simplest:

function dropTiles(callback) {
    //...
    function step() {
        //...
        if (!finished) {
            window.requestAnimationFrame(step);
        }
        else
        {
            if(callback)callback();
        }
    }
    window.requestAnimationFrame(step);
}

So now when you call drop, you can

drop(function(){
    //this code runs when drop is finished
});

If you need to wait for many drops to finish, you might choose to use Promises instead. (hint: Promises are here to stay... you should really learn how to use them).

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

Now you can:

drop().then(function(){
    //drop is finished
});

or

Promise.all([drop(), drop(), drop()]).then(function(){
    //all the drops finished
});

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745396361a4625897.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信