How To Draw Images Onto Your HTML5 Canvas
Good game logic and mechanics keep players to your game. But good graphics get them to look at your game in the first place.

Pre-requisites

Setup

Foreword

The tutorials here in general make a basic assumption that you are not a total newbie to programming or basic html. The walkthrough of the codes will zoom in and highlight areas that are crucial to creating the game, but expects some basic understanding of html as well as how to code in Javascript.

Also, in the name of clarity and ease of explanation, optimization of codes is not done.

Getting Started

We will be using a very basic html here with a game canvas object. It links to the javascript file called game.js which will contain some codes to write onto the canvas. It also links to the javascript file constants.js which will contain some static values to initialise the game. For completeness sake, this is how the html file looks like.

edited html

If you have gone through the earlier Set Up tutorial, you'll realise that it is the same. In fact, for subsequent tutorials, we will not be making much modifications to this html file.

In games, we usually use something known as a sprite sheet for our sprites (the things that move on your screen). There are many sites out there that allows you to download some form of a sprite sheet, but one of my favourite is Charas. This site allows you to build your own sprite sheets... cool stuff.

Play around in Charas to generate your very own sprite sheet. This is how a completed sprite sheet looks like.

sprite sheet

You can see that there are various poses of this cool-looking jap girl, which we will be using as our main character. Save this image in an img folder together with the rest of your html and javascript files. Your files should be organised as below.

file structure

The img folder contains a single file, which is the sprite sheet.

file structure sprite sheet

Step 1 - Preload the image

Now, if you have been running the html files off your hard disk, locally, this is a good time to think about how differently your game will behave when it is uploaded onto the web. Javascript files and definitely image files, do not load instantly. Therefore, before the game starts, it is a good practice to pause the game in a loading screen until your game assets (including your images) are loaded.

The codes below show how the object to be preloaded is set up.

//---------------
//Preloading ...
//---------------
//Preload Art Assets
// - Sprite Sheet
var charImage = new Image();
charImage.ready = false;
charImage.onload = setAssetReady;
charImage.src = PATH_CHAR;

function setAssetReady()
{
	this.ready = true;
}

Line 16 creates a new object of the Image class and assigns it to the variable charImage. We dynamically create an attribute of the charImage object and name it ready, and set it to an initial value of false in line 17. We will see this being used later on when we keep polling this ready attribute to see if it is true.

Line 18 then sets the onload variable to the function setAssetReady. What this does is that once the charImage is loaded, the setAssetReady function will trigger. Line 19 then finally tells the system that the source image for charImage can be found in the path specified by PATH_CHAR (which is found in the constants file to be "img/spritesheet.png").

Lines 21 to 24 show that the method setAssetReady sets the ready attribute to true when it is called.

//Display Preloading
ctx.fillRect(0,0,stage.width,stage.height);
ctx.fillStyle = "#000";
ctx.fillText(TEXT_PRELOADING, TEXT_PRELOADING_X, TEXT_PRELOADING_Y);
var preloader = setInterval(preloading, TIME_PER_FRAME);
var gameloop, currX, currY;

function preloading()
{	
	if (charImage.ready)
	{
		clearInterval(preloader);
		
		gameloop = setInterval(update, TIME_PER_FRAME);
	}
}

Lines 27 to 29 prepare the game stage to show the text "Loading ..." while the game is fetching the sprite sheet over the internet. Depending on the player's internet connection, it may or may not take long.

Line 30 creates a looping function called preloading which will run 30 times every second. You can see from lines 33 to 41 that what this function does is to keep polling whether the ready attribute of charImage has been set to true. The only time it will be set to true is when the image is loaded as we saw earlier.

This image below shows what you will see when the game is still loading the graphics.

loading screen

Once the sprite sheet has loaded, the game loop takes over, and the update function is executed. This is what you should see when the game loop executes. We will go into details of the game loop in the next step.

graphics loaded onto canvas

Step 2 - Draw the Image onto the Canvas

Let us now examine the codes in the game loop that draws the image onto the canvas.

//------------
//Game Loop
//------------
currX = IMAGE_START_X;
currY = IMAGE_START_Y;

function update()
{		
	//Clear Canvas
	ctx.fillStyle = "grey";
	ctx.fillRect(0, 0, stage.width, stage.height);	
		
	//Draw Image
	ctx.drawImage(charImage,currX,currY,CHAR_WIDTH,CHAR_HEIGHT,
					CHAR_START_X,CHAR_START_Y,CHAR_WIDTH,CHAR_HEIGHT);

Lines 52 and 53 wipe the entire game stage with a grey rectangle before drawing the image onto it. This is important so that the graphics are not messed up by frames drawn in the previous game tick.

The real magic happens in line 56. drawImage looks like a very complex method that takes in 9 parameters. Once you understand it, you'll realise that it's easy as pie. Take a look at the image below.

draw image explanation

We know that the entire sprite contains all 12 different poses of the cartoon girl. But what we saw on the game stage is only 1 pose. How did that happen? The diagram above shows how the parameters of drawImage control what is drawn onto the canvas.

You can see that the first parameter tells the game which image to draw. Clearly, we have only 1 image so far and it is charImage. Parameters 2 and 3 tell the game which coordinates in the sprite sheet ( (0,0) starts at the top left corner) to start picking the image from. Parameters 4 and 5 tell the game how wide and how tall the image to be drawn onto the screen, is.

draw image explanation 2

The next 2 parameters then tells the game where to draw the image onto in the game canvas. CHAR_START_X and CHAR_START_Y (both referring to values of 200) are used as the x and y coordinate respectively. Since both contain the value of 200, you can see that they are drawn at the position of (200,200) in the game canvas.

The last 2 parameters provide a quick and easy way to enlarge or shrink your image. If you want the image to double in size on-the-fly, for example, simply use CHAR_WIDTH*2 and CHAR_HEIGHT*2 as the last 2 parameters. You will see that the image drawn doubled. To keep the size the same as what you see in the sprite, simply pass back the CHAR_WIDTH and CHAR_HEIGHT.

Step 3 - Animating the Sprite

The last step will just illustrate the illusion of movement for the girl to walk. To make it convincing, I'll be using Photoshop to remove away the green background (henceforth, the better spritesheet is saved as spritesheet2.png and the final demo will be using that instead).

//------------
//Game Loop
//------------
currX = IMAGE_START_X;
currY = IMAGE_START_Y;

function update()
{		
	//Clear Canvas
	ctx.fillStyle = "grey";
	ctx.fillRect(0, 0, stage.width, stage.height);	
		
	//Draw Image
	ctx.drawImage(charImage,currX,currY,CHAR_WIDTH,CHAR_HEIGHT,
					CHAR_START_X,CHAR_START_Y,CHAR_WIDTH,CHAR_HEIGHT);
	
	currX += CHAR_WIDTH;
	if (currX >= SPRITE_WIDTH)
		currX = 0;
}

We add in two variables to track where the x and y positions of the sprite to be drawn onto the canvas should be. By manually checking the sprite sheet, we know that to draw the girl moving from left to right, the x-coordinate will still be 0, and the y-coordinate will start from 96.

In the drawImage method, instead of using (0,0) as the coordinates to pick from the sprite sheet, we dynamically use currX and currY.

Line 59 will increase the currX by the CHAR_WIDTH as the game loop ticks once, and that effectively draws the next sprite. To loop it back, line 60 will check if currX has exceeded the width of the sprite sheet, and if so, reset it back to 0.

You should be able to observe that the girl is now running on the spot, albeit a little too fast.

girl walking

 

Until Next Time

This simple tutorial explains the bare minimum codes you need to write to draw an image onto the HTML5 game canvas. If the fast running speed of the girl bothers you, you can always increase the value of TIME_PER_FRAME in the constants file. Later on in the game tutorials, we'll be showing other ways to achieve a more natural running speed.

Downloads

You can view the demo of this tutorial here (opens in new window).

You can download the files used in this tutorial here.