2017-02-19 89 views
2

对于此,必须有一个非常简单的解决方案,因为我尝试过使用setInterval()来搞乱,但似乎无法获得我想要的结果。 。globalTick()中的每个精灵的延迟tick()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]) 
} 

然后,我有这个打勾()方法在我的精灵,在这种情况下,一个箭头对象

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 
       // ... 

伊夫幸免你们变量声明。

我想要的是延迟每个新的箭头被推入到另一个对象内存在的设定时间,例如在示例中说3秒。是否有可能通过requestAnimationFrame每秒调用60次左右的globalTick()来减慢速度?理想情况下,在纯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()