为此,必须有一个非常简单的解决方案,因为我尝试将setInterval()弄乱了,但似乎无法获得我想要的结果...

我有这个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])
}


然后我在精灵上有这个tick()方法,在这种情况下,是一个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
                // ...


香港专业教育学院避免了你们的变量声明。

我想要的是将每个新的Arrow延迟到另一个对象内存在的设置时间后延迟,在示例中可以说3秒钟。甚至是否有可能在requestAnimationFrame调用的60秒左右的globalTick()中变慢?理想情况下,在纯JS中,除非使用JQuery是唯一的方法...

非常感谢,希望这足够清楚!

最佳答案

这是使用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的时间不是很准确-仅确保最小延迟。如果需要时间准确性,则必须这样计算经过时间:

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


在您的globalTick游戏循环中:

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


在spawnArrow函数中,您可以设置:

lastSpawnArrowTime = elapsedTime()

关于javascript - 延迟globalTick()JS中每个Sprite的tick(),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42322662/

10-09 14:27