在globalTick()JS

时间:2017-02-19 01:29:51

标签: javascript jquery requestanimationframe

必须有一个非常简单的解决方案,因为我已经尝试搞乱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()方法,在本例中是一个箭头对象

    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是唯一的方法......

非常感谢,希望这很清楚!

1 个答案:

答案 0 :(得分:0)

这是使用setTimeout队列的解决方案。

部分应用的> nm -DC /usr/lib64/libc++_shared.so | grep 'std::__1' === lots of output === > nm -DC /usr/lib64/libc++_shared.so | grep 'std::basic' === nothing === > nm -DC /usr/lib/gcc/x86_64-pc-linux-gnu/6.2.0/libstdc++.so.6 | grep 'std::__1' === nothing === > nm -DC /usr/lib/gcc/x86_64-pc-linux-gnu/6.2.0/libstdc++.so.6 | grep 'std::basic' === lots of output === 函数被推入队列。 spawnArrow从队列中删除第一个函数并调用它。

JSFiddle demo

spawnQueue.shift()();
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
        });
    }
}

注意:setTimeout不是非常准确的时间 - 它只能保证最小延迟。如果您需要时间准确性,则需要计算如下所用的时间:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>spawnArrows</button>

在你的globalTick游戏循环中:

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

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

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