Jeremy Abroad

Tips for developing a 2D HTML5 Canvas Javascript game

October 01, 2015

I recently had the pleasure of creating a 2D HTML5 Canvas game from scratch. Here are some tips and takeaways that might save you some time if you intend to do the same.

1. Use requestAnimationFrame()

Use this instead of setTimeout for your game loop. Here’s a polyfill you can use for cross-browser support:

window.requestAnimationFrame = window.requestAnimationFrame
    || window.webkitRequestAnimationFrame
    || window.mozRequestAnimationFrame
    || window.msRequestAnimationFrame
    || function(callback) { return setTimeout(callback, 1000 / 60); };

2. Make sure your game engine takes into account the varying time delta (because requestAnimationFrame does not guarantee a consistent FPS)

If you do not take into account the varying time delta between consecutive iterations of your game loop when using requestAnimationFrame, then your game or simulation will run differently each time. This is bad. (Also, see #5)

3. Use performance.now() for precision timing

Here’s a polyfill you can use in case the browser doesn’t support the performance API:

window.performance = window.performance || {};
window.performance.now = (function() {
  return performance.now       ||
         performance.mozNow    ||
         performance.msNow     ||
         performance.oNow      ||
         performance.webkitNow ||
         function() { return new Date().getTime(); };
})();

4. When using ctx.fillRect(x, y, width, height), make sure that x and y are integers to avoid blurriness

fillRect(x, y, width, height) renders a rectangle on the Canvas. The problem is that when x or y is not an integer, the rectangle is going to look blurry.

The solution? Ensure that x and y are always integers by rounding.

If you’re not afraid of modifying native prototypes, here’s a function you can define that could be used instead of fillRect():

CanvasRenderingContext2D.prototype.fillRectClean = function (x, y, width, height) {
  this.fillRect(Math.round(x), Math.round(y), width, height);
};

5. Don’t attempt to build your own physics engine from scratch if you intend on actually finishing your game

Do not underestimate the amount of work involved in building a physics engine. Basic tile-based collision isn’t a big deal (eg. 2D Pokemon game), but anything more complex (eg. Angry Birds) is going to take a lot more work than you probably think it will.

Detecting whether rectangles and circles are intersecting is easy. But what if the two objects are moving so fast that they go through each other and never technically intersect (solution: continuous collision detection or limiting velocities)? What if you have a million objects and performance is taking a severe hit (ever heard of a QuadTree)? Detecting collisions is one thing, but the resolution itself is even harder and requires a good understanding of physics (do the terms impulse resolution and collision normal mean anything to you?). Oh and what if you want to add rotation into the mix? What about more complex shapes like polygons, both concave and convex?

If you’re smart and willing to dive deep into physics and computer science, then sure you’ll be able to figure it out because these are solved problems with resources out there to help you learn. But if your goal is to make a game, then you’ll save yourself a whole lot of time and headache by not reinventing the wheel and just using an existing battle-tested physics engine.

If you’re not convinced, take a look at the source code of Matter.js to get an idea of what’s involved. And keep in mind that Matter.js is still in alpha status and has bugs (eg. in the “Mixed Shapes” demo you can sling objects through the walls).

6. You should probably just use Unity

I hate to say it, but you’re probably just better off using Unity. Making a game is an extremely daunting task, and Unity simplifies things tremendously, allowing you to focus exclusively on the content of the game without being bogged down by extraneous things (eg. game engine design, physics, making a level editor, handling sprites, sound, etc.). And Unity enables you to export to any platform (iOS, Android, Oculus, consoles, etc).

If you really want to stick with HTML5/Javascript, you’d save a ton of time by using a framework like Phaser.


As someone who prefers Open Source and enjoys the process of building the game engine more than building the actual game itself, it pains me to say “just use Unity”. But for the majority of games out there that don’t require anything too crazy, using an established game engine like Unity or Unreal is probably your best bet.

But by all means build your own game engine from scratch for the sake of intellectual curiosity. Just realize that you’re probably reinventing the wheel.


Jeremy Bernier

Written by Jeremy Bernier who left the NYC rat race to travel the world, work remotely, and find the meaning of life.