BIT-101 [2003-2017]

JavaScript Day 20: SpriteSheets


Today we’ll look at a few other things to do with images. We’ll start with a simplified html file:

[php lang=“HTML”]

[/php]

Note that now we only have the canvas. We will be loading the image dynamically in JavaScript. There’s more than one way to create an image in JavaScript. You can use document.createElement() or use some built in jQuery stuff, or go bare bones and just say new Image(). You then set its source and wait for it to load. This looks like this:

[php lang=“JavaScript”]image = new Image();
image.src = “someImage.png”;
image.onload = function() {
// do something with the image now that it is loaded.
}[/php]

In today’s example we’ll be using the third version of drawImage to implement a sprite sheet. Quick definition: a spritesheet is a large image filled with smaller images. When you display each of the smaller images in the correct order, you get an animation. If you imagine an old celluloid movie reel, unrolled, chopped up, and laid out in a large square, you have the idea of a sprite sheet. While such a contraption would be tough to play back smoothly on a physical device, it’s just a matter of some simple math to make a computer do it.

I’ve used my tool, SWFSheet to generate the sprite sheet you see here:

Full size, it is 512×512, with 6o frames, each one 60×60 pixels.

The third overload for drawImage looks like this:

context.drawImage(image, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH);

Args 2-5 define a rectangle in the source image you are drawing. 6-9 define the rectangle on the canvas you want to draw into. The destination in this case will always be the same: 0, 0, 60, 60.

The source rect will start out 0, 0, 60, 60, then move to 60, 0, 60, 60, then 120, 0, 60, 60 and so on until it hits the last frame in the first row. Then it will become 0, 60, 60, 60, then 60, 60, 60, 60, and 120, 60, 60, 60 and so on for that row. We’ll keep track of how many frames we’ve drawn so that when we’ve reached the last one, we start again at 0, 0. Just imagine marching across the top row of a chess board, then the second row, third row, etc, then back to the beginning. Of course, this will be done in a setInterval so that each frame shows after a short delay.

If you vaguely understood that explanation, you should be able to piece together the following code:

[php lang=“JavaScript”]$(function () {
var canvas, context, image, width, height, xpos = 0, ypos = 0, index = 0, numFrames = 60, frameSize = 60;

image = new Image();
image.src = “spritesheet.png”;
image.onload = function() {
width = image.width;
height = image.height;
canvas = $("#canvas")[0];
context = canvas.getContext(“2d”);

setInterval(function () {
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(image, xpos, ypos, frameSize, frameSize, 0, 0, frameSize, frameSize);
xpos += frameSize;
index += 1;
if(index >= numFrames) {
xpos = 0;
ypos = 0;
index = 0;
}
else if(xpos + frameSize > width) {
xpos = 0;
ypos += frameSize;
}
}, 1000/24);
};
});[/php]

First we create and load the spritesheet image. When it’s loaded, we get the canvas, context, width and height of the image and start the interval.

In the interval function, we clear the canvas and draw the correct chunk of the source image to the canvas. We then have some not so elegant code to find the next rectangle to draw. I trust you’ll be able to work through all this. And the result:

https://www.bit-101.com/jscanvas/mar20.html

Flash animations converted to pure html5! Wallaby Schmallaby! 😉

« Previous Post
Next Post »