To allowFirst Rq : A key rule in Javascript : avoid system lag, with a very simple principle : do not feed the game to pausegarbage collector.
So : Reuse your Arrays, do not create closures, use integers and evennot strings, pool your objects, ... a lot of simple rules too long to go faster orexplain in a few words.
Now that you've done that, to avoid a slow-motiondown/ fast forward behaviour, you have to to to handle the time and timers by yourself. And drop a frame or more if you have to.
Rq : A secondary benefit of handling your game time/timers is that it will allow to nicely pause the game, and even to go faster or bullet-time if you want.
So how to handle your game time ?
So insideInside your run() loop you should measure the time between two calls (delta),
and add up that 'real' time to your game time... Unless (and that's the trick)
too much time elapsed (there was a pause or a system lag) : in that case
you consider that just one frame elapsed.
Scale that time delta to allow bullet time / fast speed.
And for the game timers either :
a) you implement your own game timers (gameSetTimeout/intervalgameSetInterval) (tricky, costlysomehow complex)
b) you only check your entities against the game time for time-related actions.
expl, for a human that turns into a zombie after a given time :
if (this.willDyeisDead && (gameTime - this.willDyeTime-*gameTime*<0DeathTime > ZombieToHumanTurnTime)) {
this.type = 'zombie';
this.willDyeisDead = false ;
this.isDeadisLivingDead = true ;
this.target = 'brain' ; // :)
}
(you can write this in a neater way with a : if (this.shouldDyeshouldTurn()) ... )
So now that you have your game time :
a), you must have your entityentities update depending on game time :
So with delta = delta between current game time and previous frame game time :
this.update ( dtdelta ) { // position update for a simple entity having velocity.
this.x = this.x + this.velocity.x*dt;x*delta; // depends on dt (ms)
this.y = this.y + this.velocity.y*dt;y*delta; // depends on dt (ms)
}
a) whenever the game is stopped (tab change in browser, ...) the time between two
frames will be > typical time : only consider that 1 frame elapsed. And your game
will just resume where it was.
b) fast/slow motion : you can choose to make the game time increment by the 'real' time, scaled by a
factor. so with a factor > 1 you go faster, and with factor < 1 you go bullet time... Nice !
(The 'dt' you use for update should be scaled also.)
noticeNotice that window.performance.now is a much more accurate timer available (with a polyfill) on almost all current platforms.