Sunday, August 22, 2010

Animating the Canvas Part 1: The Immediate Problem

This blog has strayed quite a bit from what I wanted when I started writing it. I want to look at game development from both the design and programming view as products are created. This article, which will be divided into an unknown number of parts due to the huge size of the topic, will get me back on track. Here I will look at the development of an HTML 5 Canvas animation system as I develop it. I will be trying to cover my train of thought as the animation system is developed to explain the choices made and why different choices might be beneficial for different projects.

One of the things that HTML 5 brings with it to the mix is the Canvas. This lets you draw things, which makes creating games that don't require a plug-in such as Flash or Silverlight much more possible. At this point in time, HTML 5 and the canvas are draft standards. This means that they are subject to change but since a lot of browsers already implement the canvas, this change would probably not be that drastic. The one thing that I am hoping will change is better support for off-canvas drawing so techniques such as double or triple buffering can be better utilised.

The canvas is what is known as an immediate mode drawing surface. This means that, in theory at least, when you draw something on the canvas it appears immediately. In reality, there are things like frame-rates and implementation issues that can alter this behaviour. Still, when working with the canvas you should always assume that your drawing happens immediately. This leads to a really big problem for animation. Animation works by drawing something in one position, then erasing it, then drawing it again in a new position.  The problem is that the erasing and re-drawing of the object can result in flickering.

The traditional way that I have solved this problem is to do the drawing in an off-screen buffer then replace the current canvas image with what is drawn in the buffer. This might be possible to do by using multiple canvases and hiding one canvas, but it is a trick which may result in all sorts of other issues. The ImageData support that the canvas does currently have can be a partial solution to the problem, but the only drawing support the ImageData objects have are direct pixel manipulation. For some games, especially tile-based games, this can be all that is needed. Other games, such as the Dozen Days series of games that is inspiring this series, require a bit more flexibility than that.

If you can't draw off-screen, then the only other real solution to this problem is to try to reduce the flicker as much as possible. The best way of reducing flicker is to only update the parts of the screen that are changing and to do so in such a way that the updated region is as completely drawn as possible. An older method, known as dirty rectangle animation, is probably the best way of dealing with this. As dirty rectangles happen to work really well with layers, this will be the approach that I will be taking.

In the next part of this series, I will be taking a look at what layers and dirty rectangles are and hopefully start coding some of the primitive classes that will be needed.

No comments: