在HTML5游戏中实现一个计时器

问题描述 投票:1回答:3

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

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

计时员

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()函数,导致倒计时非常快。

任何人都可以帮我解决这个问题吗?

提前致谢。

javascript html5
3个回答
1
投票

setInterval函数堆栈,意味着它将继续创建setInterval实例。通过反复调用timeBoard.update(),您将创建许多setInterval实例,使您的计时器运行速度超过应有的速度。您可以将update方法更改为类似init的方法,然后在动画循环外调用一次。


1
投票

您需要让计数器在animate框架循环方法之外运行。您可以在函数中添加某种计时器来补偿帧(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);

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


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)
© www.soinside.com 2019 - 2024. All rights reserved.