2017-01-03 2 views
0

Я пишу небольшую игру в Vue.js, как инкрементальный, и у меня проблемы с моим таймером. Планируется, что игра будет направлена ​​на мобильный через Кордову, когда пользователь переключит приложения или заблокирует телефон, запускается timer.stop() и возобновляется, когда страница снова становится фокусом. Мне не нужно, чтобы игра обновлялась многократно, раз в секунду или 0,5/с достаточно (отсюда кнопка скорости).Таймер Javascript desynchronizes

Вот моя проблема: когда я быстро останавливаюсь и возобновляю игру, таймер выходит из-под контроля и ускоряется до тех пор, пока я не приостанавливаюсь и не возобновляю таймер снова. Video link для лучшего объяснения.

Код таймера:

const {EventEmitter} = require('events') 

module.exports = class Game extends EventEmitter { 
    constructor (options = {}) { 
    super() 

    this.framesPerSecond = options.framesPerSecond || 60 
    this.maxFrameSkip = options.maxFrameSkip || 10 
    this.waitTime = options.waitTime || 0 

    this._nextTick = Date.now() 
    this._lastTick = 0 
    this._updateTicks = 0 
    this._running = false 
    } 

    get isRunning() { 
    return this._running 
    } 

    get updateTicks() { 
    return this._updateTicks 
    } 

    get currentTick() { 
    return this._updateTicks % this._framesPerSecond 
    } 

    set framesPerSecond (framesPerSecond) { 
    this._framesPerSecond = framesPerSecond 
    this._skipTicks = Math.floor(1000/framesPerSecond) 
    } 

    get framesPerSecond() { 
    return this._framesPerSecond 
    } 

    set maxFrameSkip (maxFrameSkip) { 
    this._maxFrameSkip = maxFrameSkip 
    } 

    get maxFrameSkip() { 
    return this._maxFrameSkip 
    } 

    set waitTime (waitTime) { 
    this._waitTime = waitTime 
    } 

    get waitTime() { 
    return this._waitTime 
    } 

    start() { 
    this.emit('start') 
    this._running = true 
    this._lastTick = this._nextTick 
    this._run() 
    } 

    stop() { 
    this._running = false 
    this.emit('stop') 
    } 

    _run() { 
    const next = this._nextTick = Date.now() 
    const max = this._updateTicks + this._maxFrameSkip 
    const skip = this._skipTicks 

    while (this._lastTick <= next && this._updateTicks < max) { 
     this.emit('update') 
     this._lastTick += skip 
     this._updateTicks++ 
    } 

    this._running && setTimeout(() => this._run(), this._waitTime) 
    } 
} 

Что я делаю неправильно или что я мог бы улучшить?

+0

Я думаю, 'this._running && SetTimeout (() => this._run(), this._waitTime)' будет установлен таймер и по истечении определенного периода времени он будет называть '() => this._run() 'Ссылка на этот таймер должна быть очищена, когда вы вызываете функцию остановки. что-то вроде [этого] (http://www.w3schools.com/jsref/met_win_cleartimeout.asp) – sandyJoshi

+0

Кажется, работает! Поместите свой комментарий в ответ, чтобы я мог его принять, спасибо! –

ответ

1

При запуске таймера вы вызываете _run через некоторый интервал времени. Пока вы приостанавливаете игру, вы не очищаете этот таймер. Это может сделать функцию _run запустить еще раз, пока вы нажимаете кнопку сразу. Вы можете использовать clearTimeout, как описано ниже.

// while pausing the timer, clears old timer reference 
stop() { 
    this._running = false 
    this.emit('stop') 
    if (this._timer) { 
     clearTimeout(this._timer); 
    } 
} 

_run() { 
    // All your code related to game. 

    // Here saving reference of timer in this._timer 
    if (this._running) { 
     this._timer = setTimeout(() => this._run(), this._waitTime) 
    } 
} 
Смежные вопросы