One of the most important parts of a game engine is the so called “game loop”. It is the central piece of the game’s engine and is responsible for trying to balance running a game’s logic, and executing its drawing operations.

A very basic game loop would look something like this in JavaScript (this does not work in Browsers!):

varGame={};Game.draw=function(){...drawentitieshere...};Game.update=function(){...rungamelogichere...};while(!Game.stopped){// While the game is runningGame.update();// Update Entities (e.g. Position)Game.draw();// Draw Entities to the Screen}

Writing a game loop for execution in the browser is a tad more tricky than that. We can’t just use a while loop that runs forever, as JavaScript execution blocks the browser from repainting its window, making the game seem to have “locked-up”.

So we’ll have to try “emulating” a real loop, while giving back control to the browser after every drawing operation to not lock-up the interface.

setInterval to the rescue!

window.setInterval is exactly what we’re looking for. It provides a way to run code in a loop while allowing the browser to repaint the window in between the loop runs.

Game.fps=50;Game.run=function(){Game.update();Game.draw();};// Start the game loopGame._intervalId=setInterval(Game.run,1000/Game.fps);...// To stop the game, use the following:clearInterval(Game._intervalId);

That’s it?

Well, yeah. At least for a basic game. The main problem with this kind of loop is that the updating and drawing operations are “glued” together (this means your game’s logic will run as fast as your drawing operations). So if your frame rate drops below 60fps, your game will also seem to be running slower.

For some games, this might never be a problem, for others this behaviour can lead to jerkiness. Also, if you want to add a multiplayer component, you want to make sure that your logic runs with the same speed on all your clients.

This can be achieved using a so called ”game loop with fixed time steps”. Basically, we try to run the logic a fixed amount of times per second, while trying to draw as many frames per second as possible.

Game.run=(function(){varloops=0,skipTicks=1000/Game.fps,maxFrameSkip=10,nextGameTick=(newDate).getTime();returnfunction{loops=0;while((newDate).getTime()>nextGameTick&&loops<maxFrameSkip){Game.update();nextGameTick+=skipTicks;loops++;}Game.draw();};})();// Start the game loopGame._intervalId=setInterval(Game.run,0);

Now, this will give us a game loop that runs 50 Game updates per second, while trying to run the drawing code as often as possible.

This gives very, very smooth animations, on my machine, I get around 200 drawing operations per second with Google Chrome, while the number of updating operations stays constant at 50 per second.

More problems?!

But now we’re facing another problem: We’re burning a lot of CPU cycles, way more than are actually needed to give our players smooth animations. Most computer screens have a refresh rate of either 50 or 60 Hz, so having 200 rendering operations per second is total overkill, and brings my CPU usage up to 48%, according to Chrome’s Task Manager.

That’s why Mozilla introduced window.mozRequestAnimationFrame (which also has a WebKit twin called window.webkitRequestAnimationFrame) a way to easily limit the number of drawing operations per second to the number of screen refreshes per second. (Currently, both mozRequestAnimationFrame as well as webkitRequestAnimationFrame do not truly sync with the screen refresh rates, but simply help in limiting drawing operations to a sane amount, but real sync will be implemented eventually.)

To be also compatible with browsers that do not implement window.*RequestAnimationFrame, we’ll have to provide a fallback based on setInterval, but limited to 60 frames per second:

Conclusion

Wow, that’s been a long journey we had to undertake to get a game loop that’s giving us both smooth animations while making sure that our game runs at a constant pace.

I’ll try to post some more articles about game development using Javascript and HTML5 over the next weeks, so make sure to check back from time to time!

Edit - February 3rd, 2010

As was pointed out in the comments, there is no benefit in running more drawing operations than update operations (except for maybe benchmarking), so you have to either interpolate or skip drawing if there were absolutely no game updates.

Skipping drawing operations is actually really easy to achieve, just put a small condition around the call to Game.draw:

if(loops)Game.draw();

This makes sure that we only draw the game if we have run at least one updating operation.

Interpolation is a bit more difficult, as you have to make all drawing operations aware of the interpolation, and it will make your game drawing code considerably more complicated.

Now, if you’re going to do interpolation, you should also lower the number of game updates you run, down to maybe 25 or 30 updates per second (but don’t forget to update the movement speed of your objects accordingly).