在HTML5游戏中实现计时器

时间:2018-09-18 02:01:31

标签: javascript html5

我正在尝试在HTML5画布上构建一个小型游戏,并且尝试在游戏中设置1分钟倒数计时器时遇到了麻烦。

以下代码包含timeKeeper函数和animate循环。

timeKeeper

function timeKeeper(width, font, posX, posY, text) {
    this.width = width;
    this.x = posX;
    this.y = posY;
    this.font = font;
    this.text = text;
    this.numSeconds = 0;
    this.time = 0;

    this.draw = () => {
        c.font = this.width + " " + this.font;
        c.fillStyle = "white";
        c.fillText(this.text, this.x, this.y);
    }

    this.update = () => {
        setInterval(() => {
            this.text -= 1;
        },1000)
        this.draw();
    }

}

动画

// Animation Loop
function animate() {
    requestAnimationFrame(animate)
    c.clearRect(0, 0, canvas.width, canvas.height)
    timeBoard.update()
    //Move enemies
    enemies.forEach((enemy) => {
        //update score and time
        scoreBoard.draw();

        //draw labels
        scoreLabel.draw();
        timeLabel.draw();

        //update enemies
        enemy.update();
        enemy.checkBoundary();
        if (enemy.isTrue == true) {
            enemies.splice(enemies.indexOf(enemy), 1);
            // console.log(enemies);
        }

        if (enemies.length == 0) {
            setTimeout(initEnemies(), 200)
        }

        //collision detection by checking color
        if (enemy.color == "#2185C5") {
            if (getDistance(enemy.x, enemy.y, ship[0].x, ship[0].y) < enemy.radius + ship[0].radius) {
                enemy.color = "#FF00FF"
                scoreBoard.update();
            }
        }
    });
    //create one particle
    ship[0].update();
}

我认为这里发生的是timeBoard.update()函数在每一帧都被调用,从而导致倒数真的很快。

有人可以帮我解决这个问题吗?

先谢谢了。

3 个答案:

答案 0 :(得分:1)

您需要让计数器在动画帧循环方法之外运行。您可以在函数内添加某种计时器来补偿帧(60fps意味着animate()大约每隔16.667ms运行一次),但是requestAnimationFrame()并不总是以60fps运行。如果浏览器无法以这种速度渲染,则会降低帧循环的速度。因此,制作与requestAnimationFrame();完全相关的计时器不是一个好主意。

相反,在函数外添加一个计数器。理想情况下,请在开始动画循环之前立即使用setInterval()。时间间隔可能看起来像这样。...

var counter = 0;
var timer = window.requestAnimationFrame(function(){
  timeBoard.update();
  if(counter+1 == 60){
    //a minute has passed, clear the interval:
    clearInterval(timer);
  }else{
    counter++;
  }
},1000);

如果您在问题详细信息中包含启动动画循环的代码,我可以帮助您确切地说明如何实现它。另外,您没有提及是否需要计数器可重复使用。这些都是要考虑的事情。如果需要可重用,则可以考虑使用面向对象的解决方案。

答案 1 :(得分:1)

setInterval函数堆栈,这意味着它将继续创建setInterval实例。通过重复调用timeBoard.update(),您将创建许多setInterval实例,从而使计时器运行得更快。您可以将update方法更改为类似init的方法,然后在动画循环之外调用该方法。

答案 2 :(得分:0)

在动画循环中称为timeBoard.draw(),以便绘制计时器。然后在动画循环外调用setInterval()函数。

谢谢大家〜:)

function animate() {
    requestAnimationFrame(animate)
    c.clearRect(0, 0, canvas.width, canvas.height)
    timeBoard.draw()
    //Move enemies
    enemies.forEach((enemy) => {
        //update score and time
        scoreBoard.draw();

        //draw labels
        scoreLabel.draw();
        timeLabel.draw();

        //update enemies
        enemy.update();
        enemy.checkBoundary();
        if (enemy.isTrue == true) {
            enemies.splice(enemies.indexOf(enemy), 1);
            // console.log(enemies);
        }

        if (enemies.length == 0) {
            setTimeout(initEnemies(), 200)
        }

        //collision detection by checking color
        if (enemy.color == "#2185C5") {
            if (getDistance(enemy.x, enemy.y, ship[0].x, ship[0].y) < enemy.radius + ship[0].radius) {
                enemy.color = "#FF00FF"
                scoreBoard.update();
            }
        }
    });
    //create one particle
    ship[0].update();
}

//Run Timer
setInterval(() => {
    timeBoard.update()
}, 1000)