2015-10-21 4 views
0

Так что я делаю небольшую игру, похожую на тетрис, где плитки падают друг на друга, уничтожаются и т. Д. Я делаю анимацию холста HTML5 через requestAnimationFrame(). Этот метод называется собирать плитки висит в воздухе и падение их вниз плавно:Как запустить 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); 
} 

Это основной способ, где выше метод вызывается из:

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

Все работает нормально, но я заметил, что сразу после того, как dropTiles() называется, управление сразу же переходит к следующей инструкции, даже если последнее еще не закончено (т.е. score() вызывается с черепицей, все еще висящей в воздухе).

Так что мой вопрос: как сделать requestAnimationFrame() синхронным и полностью закончить до того, как управление выйдет из моего метода dropTiles()?

ответ

4

У вас нет. Вы переписываете свой метод drop на уведомлять вы, когда это будет сделано. В самом простом:

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

Так что теперь, когда вы звоните drop, вы можете

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

Если вам нужно ждать много drop секунд до конца, вы можете выбрать, чтобы использовать вместо Promises. (Подсказка: обещания здесь остаться ... вы должны действительно научиться их использовать).

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

Теперь вы можете:

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

или

Promise.all([drop(), drop(), drop()]).then(function(){ 
    //all the drops finished 
}); 
Смежные вопросы