2017-02-19 14 views
2

Для этого должно быть действительно простое решение, поскольку я попытался возиться с setInterval(), но не могу получить результат, который я хочу. .Delay tick() каждого спрайта в globalTick() JS

у меня есть этот globalTick()

function globalTick(){ 
    ctx.clearRect(0,0,800,800) 

    if(target){ 
     target.tick(); 
    } 

    // Move arrows 
    for(var i = 0; i < spriteList.length; i++){ 
     spriteList[i].tick() 
    } 


    window.requestAnimationFrame(globalTick); 
} 

document.onkeyup = function(e){ 
    // Change gamestate 
    if(e.which == 13){ 
     $("#state"+gameState).hide() 
     gameState ++ 

     if(gameState == 6){ 
      // Affect game variables 
      player = new Player(0); 
      target = new Target(targetX, targetY) 

      for(var i = 0; i < player.calculateNotes(); i++){ 
       timerID = setInterval(spawnArrows(), 3000) 
      } 
      clearInterval(timerID) 
    } 

    // ... 

spawnArrows = function(){ 
    // Rabdomize arrows (15 for now) 
    var dirCode = Math.floor((Math.random() * 8)); 
    spriteList.push(new Arrow(dirCode)) 
    //soundsSequence.push(soundsList[dirCode]) 
} 

Тогда у меня есть этот клещ() метод на моих спрайтов, в этом случае объект Arrow

class Arrow{ 
     constructor(dirCode){ 
      this.dirCode = dirCode; 
      this.speedX = 1 
      this.speedY = 1 

      switch(this.dirCode){ 
       // ... 
      } 

    tick(){ 
      ctx.fillStyle = "black" 
      ctx.fillRect(this.x, this.y, spriteSize, spriteSize) 

      switch(this.dirCode){ 
       case 0: 
        this.x += this.speedX 
        break 
       case 1: 
        this.x += this.speedX 
        this.y -= this.speedY 
        break 
       // ... 

Ive пощадил вас, ребята переменную деклараций.

То, что я хочу, - это задержать каждую новую стрелку, вдвинутую в массив, на установленное время, которое существует внутри другого объекта, скажем, 3 секунды в примере. Можно ли даже замедлить работу в globalTick(), который называется 60 раз или около того по запросуAnimationFrame? Идеально в чистом JS, если только JQuery - единственный способ пойти ...

Большое спасибо, надеюсь, что это достаточно ясно!

+0

Посмотрите здесь http://stackoverflow.com/questions/42318765/how-can-i-make-3-thousand-requests-to-google-drive-api-using-node-js-without-exc Я объяснил как сделать водопад с обещаниями –

ответ

0

Вот решение, использующее очередь setTimeout.

Частично применены функции spawnArrow, введенные в очередь. spawnQueue.shift()(); удаляет первую функцию из очереди и вызывает ее.

JSFiddle demo

let notes = ["A", "B", "C", "D", "E"]; 
 
let spriteList = []; 
 
let spawnQueue = []; 
 
let delayTime = 500; 
 

 
function globalTick() { 
 
    spriteList.forEach(sprite => sprite.tick()); 
 
    requestAnimationFrame(globalTick); 
 
} 
 
globalTick(); 
 

 
$('button').click(onButtonClick); 
 

 
function onButtonClick() { 
 
    let kickOffQueue = spawnQueue.length <= 0; 
 

 
    notes.forEach(note => 
 
     spawnQueue.push(() => spawnArrow(note)) 
 
    ); 
 

 
    if (kickOffQueue) { 
 
     // here you can set the delay time of the first execution 
 
     consumeSpawnQueue(500); 
 
    } 
 
} 
 

 
function consumeSpawnQueue(nextDelayTime) { 
 
    if (spawnQueue.length > 0) { 
 
     setTimeout(() => { 
 
      spawnQueue.shift()(); 
 
      consumeSpawnQueue(delayTime); 
 
     }, nextDelayTime); 
 
    } 
 
} 
 

 
function spawnArrow(note) { 
 
    var dirCode = Math.floor((Math.random() * 8)); 
 
    spriteList.push(new Arrow(dirCode, note)); 
 
} 
 

 
class Arrow { 
 
    constructor(dirCode, note) { 
 
     this.dirCode = dirCode; 
 
     this.x = 0; 
 
     this.domEl = $(`<div>${note}${dirCode}</div>`).appendTo('body'); 
 
    } 
 

 
    tick() { 
 
     this.x += 1; 
 
     this.domEl.css({ 
 
      marginLeft: this.x 
 
     }); 
 
    } 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<button>spawnArrows</button>

Примечание: SetTimeout не очень много времени точный - это только gaurentees минимальной задержки. Если вам нужна точность времени, то вместо этого нужно вычислить истекшее время, как это:

const startTime = new Date(); 
const elapsedTime =() => (new Date() - startTime)/1000; 

в цикле globalTick игры:

if ((elapsedTime() - lastSpawnArrowTime) > delayTime) { 
    spawnQueue.shift()(); 
} 

И внутри функции spawnArrow, вы должны установить:

lastSpawnArrowTime = elapsedTime()