HTML5 Canvas [51]
context.drawImage(tileSheet, sourceX, sourceY,32,32,50,50,32,32);
Here, we are passing the calculated sourceX and sourceY values into the drawImage() function. We then pass in the width (32), the height (32), and the location (50,50) to draw the image on the canvas. Example 4-5 shows the full code.
Example 4-5. Advanced sprite animation
var tileSheet = new Image();
tileSheet.addEventListener('load', eventShipLoaded , false);
tileSheet.src = "tanks_sheet.png";
var animationFrames = [1,2,3,4,5,6,7,8];
var frameIndex = 0;
function eventShipLoaded() {
startUp();
}
function drawScreen() {
//draw a background so we can see the Canvas edges
context.fillStyle = "#aaaaaa";
context.fillRect(0,0,500,500);
var sourceX = Math.floor(animationFrames[frameIndex] % 8) *32;
var sourceY = Math.floor(animationFrames[frameIndex] / 8) *32;
context.drawImage(tileSheet, sourceX, sourceY,32,32,50,50,32,32);
frameIndex++;
if (frameIndex ==animationFrames.length) {
frameIndex=0;
}
}
function startUp(){
setInterval(drawScreen, 100 );
}
When we run the example, we will see the eight tile cell frames for the tank run in order and then repeat—the only problem is that the tank isn’t going anywhere. Let’s solve that little dilemma next and drive the tank up the screen.
Moving the Image Across the Canvas
Now that we have the tank tracks animating, let’s “move” the tank. By animating the tank tracks and applying a simple movement vector to the tank’s position, we can achieve the simulation of animated movement.
To do this, we first need to create variables to hold the current x and y positions of the tank. These represent the top-left corner where the tile from our sheet will be drawn to the canvas. In the previous examples, this number was set at 50 for each, so let’s use that value here as well:
var x = 50;
var y = 50;
We also need a movement vector value for each axis. These are commonly known as deltaX (dx) and deltaY (dy). They represent the “delta” or “change” in the x or y axis position on each iteration. Our tank is currently facing in the “up” position, so we will use -1 for the dy and 0 for the dx:
var dx = 0;
var dy = -1;
The result is that on each frame tick, our tank will move one pixel up on the y-axis and zero pixels on the x-axis.
Inside drawScreen() (which is called on each frame tick), we will add the dx and dy values to the x and y values, and then apply them to the drawImage() function:
y = y+dy;
x = x+dx;
context.drawImage(tileSheet, sourceX, sourceY,32,32,x,y,32,32);
Rather than use the hardcoded 50,50 for the location of the drawImage() call on the canvas, we have replaced it with the current x,y position. Let’s examine the entire code in Example 4-6.
Example 4-6. Sprite animation and movement
var tileSheet = new Image();
tileSheet.addEventListener('load', eventShipLoaded , false);
tileSheet.src = "tanks_sheet.png";
var animationFrames = [1,2,3,4,5,6,7,8];
var frameIndex = 0;
var dx = 0;
var dy = -1;
var x = 50;
var y = 50;
function eventShipLoaded() {
startUp();
}
function drawScreen() {
y = y+dy;
x = x+dx;
//draw a background so we can see the Canvas edges
context.fillStyle = "#aaaaaa";
context.fillRect(0,0,500,500);
var sourceX = Math.floor(animationFrames[frameIndex] % 8) *32;
var sourceY = Math.floor(animationFrames[frameIndex] / 8) *32;
context.drawImage(tileSheet, sourceX, sourceY,32,32,x,y,32,32);
frameIndex++;
if (frameIndex==animationFrames.length) {
frameIndex=0;
}
}
function startUp(){
setInterval(drawScreen, 100 );
}
By running this example, we see the tank move slowly up the canvas while its tracks play through the eight separate tiles of animation.
Our tile sheet only has images of the tank facing in the up position. If we want to have the tank move in other directions, we can do one of two things. The first option is to create more tiles on the tile sheet to represent the left, right, and down positions. However, this method requires much more work and creates a larger source image for