我正在尝试在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()
函数,导致倒计时非常快。
任何人都可以帮我解决这个问题吗?
提前致谢。
setInterval
函数堆栈,意味着它将继续创建setInterval
实例。通过反复调用timeBoard.update(),您将创建许多setInterval实例,使您的计时器运行速度超过应有的速度。您可以将update
方法更改为类似init
的方法,然后在动画循环外调用一次。
您需要让计数器在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);
如果您在问题详细信息中包含启动动画循环的代码,我可以帮助您准确显示如何实现它。此外,您没有提到您是否需要计数器可重复使用。这些都是需要考虑的事情。如果您需要它可重用,您可以考虑使用面向对象的解决方案。
在动画循环中调用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)