Rendering graphics in JavaScript games

Tags:

As I’ve been rewriting TankWar, I’ve been thinking of various approaches to displaying the game’s graphics. At the moment, I can count three feasible approaches for rendering game graphics:

  • DHTML – In other words, using divs with images and moving them around
  • Canvas
  • A hybrid: Canvas with DHTML

I’ve considered each of these, and they all have some pros and cons which we’ll look at next.

DHTML

This is the most compatible of the three: Even Internet Explorer supports creating divs and moving them around on the fly.

This approach is quite simple too. The APIs used are well-known and usually quite problem-free when used correctly.

Moving divs etc. around tends to be pretty fast too, so even if you have a big huge animated explosion or something, the performance should still be relatively good. Compared to canvas this is DHTML’s biggest win.

One of the downsides with DHTML is sometimes jerky movements: You always need to draw and move things pixel-precise, as you can’t tell a div to be exactly 15.5 pixels from something. Canvas can draw “between” pixels, as it automatically aliases the graphics to look more like it.

With DHTML you also can’t draw shapes like you can with canvas, so you’ll need to come up with the graphics in an image editor beforehand.

With CSS transitions and other tricks, you can bend DHTML surprisingly far. However if using transitions or other advanced features, you sacrifice compatibility with more browsers than you would if you were just using canvas.

Canvas

Canvas is great. I wish I could leave it at that.

However, in addition to being generally easy to use after getting familiar with the basic API, there is one significant downside: Canvas is slow. Slow slow slow slow slow.

Unless you apply considerable amount of thought into the code, getting stuff drawn at reasonable speeds with canvas is difficult. It’s like going back to the times when computers had 66 mhz CPUs.

Canvas does have a lot of good things though: You can draw on it directly, with direct pixel manipulation, a vector-like API, or images.. or compose a new image using another canvas.. It is certainly very flexible, and it makes it very simple to do complex and dynamic shapes that would be much trickier otherwise.

If you’ve been following the TankWar 2.0 development, you may have noticed it does draw some okay looking graphics but it still is somewhat reasonable quick. It only uses canvas for rendering, so yes, it is indeed doable, but it requires tricks.

I’ll be discussing the finer details of how to make canvas rendering faster in another post.

Hybrid

A hybrid graphics engine is exactly what it sounds like: It combines both DHTML and canvas to overcome the downsides of both approaches.

While this may sound like the stone to drop two birds with, it may not be.

One of the good things about this approach is easily seen when you need to display large graphics that move. Canvas can be very slow in cases where you update larger areas of it, so in a case like this using a div for the big graphic is good. Then, you can use canvas for the rest, to create different shapes etc. which would be tricky with divs.

The main downside of this approach is complexity. Since you need to deal with both canvas and DOM, it’ll become twice as complex as using either of the approaches alone.

In closing

The approach I’ve chosen for TankWar 2.0 is pure canvas. I may need to resort to a hybrid approach if the performance drops too low, but right now it’s still tolerable at least on a moderately quick PC.

In the past, I’ve used canvas on most of my games: TankWar, Opera Command, WidgetRacer, Asteroids… but I’ve also used a DHTML-like approach in a Tetris game and in WidgetCity. In these cases the DHTML-based approach was simpler or had other reasons, such as being much faster in case of WidgetCity (My post about the table/CSS rendering in WidgetCity).

I’ll be discussing the details of how the new TankWar 2.0 canvas engine works in a later post. I’ve had to do a significant amount of performance trickery for it too.