Javascript Game Foundations - The Game Loop

Ten Essential Foundations of Javascript Game Development

The Game Loop

In board games, card games, and text-adventure games, the game updates only in response to player
input, but in most video games the state updates continuously over time. Entities move, scores
increase, health decreases, and objects fall, speed up, and slow down.

Therefore we need a game loop that can update() and render() our game world.

When running in the browser, all javascript code is executed in a single thread, the UI
thread (not counting WebWorkers). Which means we can’t run a naive infinite game loop:

while(true) { // UH OH! - blocks UI thread
update();
render();
}

This would block the UI thread, making the browser unresponsive. Not good.

RequestAnimationFrame

Instead, the browser provides asynchronous mechanisms for us to “do a little work”, then let the
browser UI do it’s job, then have it callback to us at a later time to “do a little more work”.

In older browsers, we might have used setInterval or setTimeout to call our update method a
set number of frames per second, but in modern browsers we should be using requestAnimationFrame
to hook into the browser’s native refresh loop:

Timestamps

While requestAnimationFrame gives us our asynchronous loop, it doesn’t guarantee exactly how
frequently it will execute. In most modern GPU accelerated browsers it will be close to 60fps, but
it might be a little more, might be a little less. If our update or render methods are slow we
might cause it to drop drastically below 60fps.

We cannot assume that 1/60th of a second passes in each frame. Therefore we need to measure
exactly how much time has passed between subsequent iterations of the loop. In modern browsers we
can use the high resolution timer
and in older browsers fallback to using a Date object:

One additional note is that requestAnimationFrame might pause if our browser loses focus,
resulting in a very, very large dt after it resumes. We can workaround this by limiting the
delta to one second:

Fixing Our Timestep

Now that we know exactly how long it has been since the last frame, we can use that information
for any math calculations within our update method.

Having a variable timestep can work for many simple games. However we gain additional
benefits if we can guarantee that the update method is called at a fixed, known, interval.

Replayable - if the timestep is variable (and unpredictable) then we cannot predictably
replay the level. If we want to be able to replay what happened we need the timestep to be
fixed and predictable

Predictable Physics - if we have a physics engine in our game, then variations in the
timestep would make it unpredictable, which might make it hard to create predictable level
design

Mitigate bullet-through-paper - depending on our collision detection scheme, we might
find that fast moving objects can pass through small objects, this can be mitigated if our
fixed timestep is set relative to our entities maximum speed and minimum size.

The idea behind a fixed timestep gameloop has been written about
thoroughly by gafferongames.com

The basic idea is to accumulate our dt until it is greater than our desired fixed timestep,
call update with the fixed timestep, and carry over the remainder to accumulate for the next
time.

We should also pass any remainder dt to our render function so it can perform smoothing LERP
calculations (if required)

BONUS: Slow Motion

As a bonus, we can (optionally) adjust the step variable and play our game in slow motion. This
can be very helpful when debugging. If we multiply step by 5, the game will play 5 times slower
(12.5 fps instead of 60fps).

Putting this all together into a final version that can be re-used by different games, we can
build a general purpose Game.run method that allows the caller to override various options: