Introduction
In this article, we’re going to look at some of the techniques used to produce animation on a canvas, like a player moving position in a game. We’ll also take a look at adding keyboard control to the box.
Before I start, I would like to advise you to read the earlier articles Beginner’s Guide to HTML5 Canvas and More Beginner HTML5 Canvas as we’re going to be making use of a lot of the techniques mentioned. Let’s know advanced coding better.
How does animation work?
Animation works by changing the properties of the element, or layer, in such small increments, that it looks smooth to the user. If you slow down animation, and make these increments larger, you’ll actually be able to see the element jumping between the different increments.
The Code
So with that, let’s get into it. The first step is, obviously, to create the canvas.
We’re also going to draw a square in the middle of the canvas.
That’s great, but as it is, this would be horrible for animation, so we need to put it in a function that can be reused much more easily. We’ll start by first defining the function, we’ll name it render. We’ll also put out current render code in there too.
We’ll also want to make sure we’re clearing the canvas before drawing to it, as it will make it easier to change our drawing later on. We’ll do this by using the function clearRect()
. This is used exactly the same way that rect()
is, but instead of drawing to the canvas, it clears it. We’ll be wanting to clear the full canvas, so we can use canvas.width
and canvas.height
for the width
and height
parameters.
The next step is to make an object to store various parameters of our square, and alter the render function to use this object. This will make updating the square later on much easier:
In order to produce animation, we must use a technique aptly named redrawing, which is where we repeatedly draw something, in this case the element, to the screen as often as possible. In the past, this was done using standard delay functions, such as setTimeout
and setInterval
, but now we can use a function called requestAnimationFrame
. However, because this is still not fully supported, we must accommodate for various browser implementations, and replicate it if it doesn’t exist at all.
That’s quite easy to do with the below block of code. This might look complex, but actually all it’s doing is attempting each variation of requestAnimationFrame
for each browser, before falling back to our own function. This works because if you ask an object (in this case window
) for a property, that doesn’t exist, it will return undefined
. Ultimately we’re saying if this property is undefined, try the next property, if that’s undefined, try the next one, etc… until we eventually just define it ourselves:
We can now make the render function redraw the square using the above function
Because we have the render function drawing the square based on the object of properties, all we have to do now is to update the square’s properties, and the render function will redraw with them.
Next, we must write the function that will actually animate the square. This function will take the property to update (out of x
, y
, width
or height
), the value to update it to, and the duration of the animation.
Inside of this function, we need to do a couple of calculations, that will help us determine the progress of the animation. We’ll reference the property they want to animate using square[prop]
, which is the same as saying square['x']
or square.x
when prop
equals 'x'
. First we calculate the time that the animation started, and then when it should end, then finally work out the distance remaining of the animation.
Because we need to increment the property in steps, we need a step function. This is also where you would do the calculations required for easing, though that is outside the scope of this tutorial.
Inside the so-called step function, we need to calculate the current progress of the function, so we can work out what to set the property to. There is a little maths behind this, but it’s quite simple. Where timestamp
is the current timestamp in the step.
However, we can never allow this number to be more than 1, otherwise the square will go further than intended, so we’ll use the Math.min
function. This function returns the smallest number out of the two arguments. So if the equation did return a number more than one, the function would still only return 1:
Using this progress
variable, we can calculate the value of the property for this stage of the animation. Lastly, we need to repeat the step function if the animation hasn’t ended yet.
With that, your animation should be working. For clarity, I’m going to give you the full animate function.
Examples
The most basic example is moving the square around, which can be done quite easily.
To move the square horizontally across the canvas, we can use the below code that will alter the x
value over 1 second:
To move the square vertically up the canvas, we can use the below code that will alter the y
value over 1 second:
To move the square diagonally we can alter both the x
and y
simultaneously:
Extending It
What if you wanted to add keyboard controls to the box? This is slightly more complex, but shouldn’t take too long to get your head around.
The idea is to start an animation for the square to move when the key is pressed down, but stop it when the key is no longer being pressed. We’ll be attaching keydown
and keyup
events in order to listen for these keys being pressed.
We can use the event variable to generate information about the movement such as the property to animate and by how far. However, we’ll be needing this in both the keydown and keyup events, so we’ll put this in a separate function.
In this meta function, we need to decide which direction the square is going, and by how far. This is actually relatively easy, once you know which key codes correlate to which direction. You can find a full reference for these key codes here, but to save time, I’ll give you the relevant ones here.
- Left: 37
- Right: 39
- Up: 38
- Down: 40
So now all we need to do is to check against the key code (contained in e.which
) and then we’ll have all the information we need. This function checks the event variable to see if we’re going up, down, left, or right. We use a ‘multiplier’ variable, to make our distance negative if we’re going left or up. We’ll also use a prop
variable to change the property we’re animating if we’re going up, or down.
Inside the keydown event, we can grab the meta information using the meta function, and then animate the square based on that information. In the key up event, we’ll stop the animation.
After adding the meta function, and the two event listeners, you should be able to move the square around the canvas using the arrow keys.
Conclusion
This should be all you need to kickstart your shiny new HTML 5 game. If you would like to see all the techniques discussed here, you can go check out this JSFiddle that I wrote during the writing of this article.