Canvas Sprite Sheet Animation

Having gone through moving shapes around screen, let’s bring our retro game tutorials up to date by about 10 years and look at sprite sheet animation.

If you have been following the series of posts linked below, then this will add to what you have done so far and you will see some things being done in a slightly different way.

If you haven’t been following this series, then it is expected that you have at least a basic understanding of HTML and Canvas/JavaScript.

If you just want to see the code for the sprite sheet animation, then skip to the bottom where I give you the code for the .html file (which should be saved to the same location as your sprite sheet).

Otherwise, I hope you find this post helpful.

 

an example of a sprite sheet animation

 

The Sprite Sheet

The sprite sheet that we will be animating is shown below.

The top row contains 3 “frames” that will be used to animate our character moving left.

The bottom row contains 3 frames that will be used to animate our character moving right.

I could also have a row with 3 frames for the character jumping and another row with frames of the character ducking.

sprite sheet example for sprite sheet animation

I used 3 frames for each direction, I could have used more frames if I wanted and I could have used better images which would have made better looking character animation… but keeping with the retro theme I deliberately went for pixelated images and “chunky” movement.

 

One third of one row will be shown on screen at any one time.

So the first third (or first character image) will be shown, then the second third and then the last third and this loops to give an animated look.

Each character in our sprite sheet will be considered a column, and rows will make up the next part of our sprite sheet, the top row is the character moving right and the bottom row is the character moving left.

 

Basic File

Let’s start by creating a basic file that we will add sprite sheet animation to as we go through this post.

Enter the code for a basic file with canvas area and save as a .html file.

I’m setting the size as 500×400 below.

<!DOCTYPE html>
<html>
<head>
<title>Sprite Sheet Animation</title>
</head>
<body>
<canvas id='canvas'></canvas>
<script>
var canvWidth = 500;
var canvHeight = 400;
var canvas = document.getElementById('canvas');
canvas.width = canvWidth;
canvas.height = canvHeight;
var ctx = canvas.getContext('2d');
</script>
</body>
</html>

first draft code for sprite sheet animation

 

Adding The Sprite Sheet

We are going to create some variables that will be used to display just the piece of the sprite sheet that we want to show at any given time.

The first variables to set up will go to around line 13, after we have set the canvHeight variable and before we have set the canvas variable.

These variables are:

  • destX – The X coordinates on our canvas that will be the top left corner of our sprite sheet (destination X)
  • destY – The Y coordinates on our canvas that will be the top edge of our sprite sheet (destination Y)
  • srcX – The X coordinates on our image that will be the top left corner of the frame we are to display (source X)
  • srcY – The Y coordinates on our image that will be the top edge of the frame we are to display (source  Y)
  • sheetWidth – The full width of our sprite sheet.  To get this, right-click on the sprite sheet in a browser window and check the properties
  • sheetHeight – Similar to above, this is the full height of our sprite sheet and you will need to get this value
  • cols – The number of columns or frames in our sprite sheet.  In my example there are 3 columns
  • rows – The number of rows of frames on our sprite sheet, in my case this is 2
  • width – the width of our frames will be calculated as the full width of our sprite sheet divided by the number of columns
  • height – the height of our frames will be calculated as the full height of our sprite sheet divided by the number of rows
  • character – we add a new image called “character”.  The source of this image will be the filename of your sprite sheet, in my case it is a file called capture.png
var destX = 300;
var destY = 150;
var srcX;
var srcY;
var sheetWidth = 499;
var sheetHeight = 459;
var cols = 3;
var rows = 2;
var width = sheetWidth / cols;
var height = sheetHeight / rows;
var character = new Image();
character.src = "capture.png";

image of code to set up sprite sheet animation variables

If you save the file and view it in a web browser, you will still see nothing because we have not yet put anything onscreen.

There will be more variables to add soon, but let’s set up the functions that we will need first.

 

addEventListener

We will control the sprite sheet animation through the arrow keys for left and right.

So, we will add the placeholder for an event listener.

This will be entered around line 36, after we set the context as 2d.

window.addEventListener('keydown', function (e) {
 
});

We will come back to coding the rest of this in a few minutes.

 

updateFrame Function

The next function will go below our eventListener.

This function will be called updateFrame, and when we add more code to it, it will update the details of the frame to be displayed.

The skeleton function is

function updateFrame() {
 
}

 

drawImage Function

The next function to go after our updateFrame function will be what adds the relevant piece of our sprite sheet to the canvas area.

The skeleton function, which we will add to looks like this:

function drawImage() {
 
}

 

setInterval function

The next, and last, function to add goes below the drawImage function.

This function will call the drawImage function every 100 milliseconds.

setInterval(function () {
drawImage();
}, 100);

 

The functions so far look like this

updated image of code for sprite sheet animation

 

Sprite Sheet Animation

Before we continue to fill in the blanks on our variable, we need to know how we are going to handle the sprite sheet animation.

Our setInterval tells the browser to call the drawImage function, so let’s start with that function.

We want drawImage to call the updateFrame function so that the browser knows what section (or frame) of our sprite sheet to display on screen.

We use the drawImage method to display part of our image on screen.

function drawImage() {
updateFrame();
ctx.drawImage(character, srcX, srcY, width, height, destX, destY, width, height);
}

The syntax for the drawImage method are:

  1. the source image, we have a variable called character
  2. the X coordinate from our source image that will be the top left corner of the sub-image to display
  3. the Y coordinate from our source image that will be the top edge corner of the sub-image to display
  4. The width of our frame which is a variable we set up
  5. The height of our frame which is another variable we set up
  6. The X coordinate of the canvas that will be the top left corner of the frame when it is displayed on the canvas
  7. The Y coordinate of the canvas that will be the top edge of the frame when it is displayed on the canvas
  8. The width of our frame which we used at point 4
  9. The height of our frame which we used at 5

 

We will now update the updateFrame function and fill in the blanks.

First, we will clear the sprite each time this function is called.

Next we will increase the frame number which will be used to calculate the frame to display.

We will add another variable at this point.  At row 28, above where you created the character variable, create a currentFrame variable with a value of zero.

var currentFrame = 0;

This value will update each time updateFrame is called and it will be divided by the number of columns to get a frame number.

 

The srcX value will be the currentFrame value multiplied by the width variable.

This gives the frame number on the columns to display, but what row should be displayed?

We will use two variables, pickRight and pickLeft.  These will be assigned numbers 0 and 1 and used to tell updateFrame what row of our sprite sheet to use.

If the left arrow key has been pressed then we want to use the row on our sprite sheet with the character moving left and vice versa for pressing the right key.

Update the updateFrame function as follows:

function updateFrame() {
ctx.clearRect(x, y, width, height);
currentFrame = ++currentFrame % cols;
srcX = currentFrame * width;
if (left)
srcY = pickLeft * height;
else
srcY = pickRight * height;
}

updated image of sprite sheet animation functions

Now we will add the pickLeft and pickRight variables, add these to the same section where you set the src and dest X and Y values and set the values as 1 and 0 respectively.

We will also add a variable called “left” and set the value to false.

update image of variables for sprite sheet animation

To recap on what we have so far.

We have a setInterval function that calls the drawImage function.

drawImage puts a frame from our sprite sheet onscreen, it bases the frame to use on a number of variables, some of which are defined by the updateFrame function.

This updateFrame function loops the frame number to be used horizontally and selects the row to pull the image from based on left, pickLeft and pickRight variables.

Now, how do we tell when left is true or false?  You may notice that our eventListener is still pretty much empty, so we’ll put the final piece in there.

From the variable we set earlier, you can see that “left” is false, we’ll change this variable depending on if the left or right arrow keys are pressed.

So, if the left arrow key (keyCode 37) is pressed, then change the left variable to be true.

Or if the right arrow key is pressed, then change the left variable to be false again.

window.addEventListener('keydown', function (e) {
if (e.keyCode == 37) {
left = true;
} else if (e.keyCode == 39) {
left = false;
}
});

sprite sheet animation event listener code

Save your file, open it in your browser, or if you have it open already, then refresh it.

You should have an animated character running left and right on your screen.

an example of a sprite sheet animation

 

From this series of posts I hope you have learned enough to try creating your old favorite retro game, at this point you haven’t seen enough to recreate a full platform game based on plumbers, mushroom people and weird dinosaur type characters…. but you have a good start.

Why not try it yourself.

For now I’m taking a break from the games posts, but I will come back to this topic with more.

Sprite Sheet Animation Full Code

<!DOCTYPE html>
<html>
<head>
<title>Sprite Sheet Animation</title>
</head>
<body>
<canvas id='canvas'></canvas>
<script>
var canvWidth = 500;
var canvHeight = 400;
var destX = 300;
var destY = 150;
var srcX;
var srcY;
var pickRight = 0;
var pickLeft = 1;
var left = false;
var sheetWidth = 499;
var sheetHeight = 459;
var cols = 3;
var rows = 2;
var width = sheetWidth / cols;
var height = sheetHeight / rows;
var currentFrame = 0;
var character = new Image();
character.src = "capture.png";
var canvas = document.getElementById('canvas');
canvas.width = canvWidth;
canvas.height = canvHeight;
var ctx = canvas.getContext('2d');
window.addEventListener('keydown', function (e) {
if (e.keyCode == 37) {
left = true;
} else if (e.keyCode == 39) {
left = false;
}
});
function updateFrame() {
ctx.clearRect(destX, destY, width, height);
currentFrame = ++currentFrame % cols;
srcX = currentFrame * width;
if (left)
srcY = pickLeft * height;
else
srcY = pickRight * height;
}
function drawImage() {
updateFrame();
ctx.drawImage(character, srcX, srcY, width, height, destX, destY, width, height);
}
setInterval(function () {
drawImage();
}, 100);
</script>
</body>
</html>
email
Follow

Get every new post delivered to your Inbox

Join other followers:

%d bloggers like this: