Реализация таймера в игре HTML5 - PullRequest
0 голосов
/ 18 сентября 2018

Я пытаюсь построить небольшую игру на холсте 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();
    }

}

1010 * одушевленные * // 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 голосов
/ 18 сентября 2018

Функция setInterval стеков, что означает, что она будет продолжать создавать setInterval экземпляры. Повторно вызывая timeBoard.update (), вы создаете много экземпляров setInterval, благодаря чему ваш таймер работает быстрее, чем должен. Вы можете изменить свой метод update на что-то вроде init, а затем вызвать его один раз за пределами цикла анимации.

0 голосов
/ 18 сентября 2018

Вызывается 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)
0 голосов
/ 18 сентября 2018

Необходимо, чтобы счетчик работал вне метода цикла анимации кадров. Вы можете добавить некоторый таймер в функцию для компенсации кадра (60fps означает, что animate() будет работать примерно каждые 16.667 мс), но requestAnimationFrame() не всегда будет работать при 60 fps. Если браузер не может выполнить рендеринг в таком темпе, он замедлит цикл кадров. Поэтому не стоит создавать таймер, который вообще связан с 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);

Если вы включите код, который запускает цикл анимации, в детали вашего вопроса, я могу помочь точно показать, как вы бы это реализовали. Кроме того, вы не упоминаете, нужен ли счетчик для повторного использования. Это все вещи для рассмотрения. Если вам нужно, чтобы его можно было повторно использовать, вы можете рассмотреть возможность использования объектно-ориентированного решения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...