Join Lee Brimelow for an in-depth discussion in this video Drawing sprite sheets, part of HTML5 for Flash Developers.
- View Offline
So if you've ever done any game development in Flash, you're probably familiar with the concept of sprite sheets, and this is essentially taking a certain animation and extracting every frame of that animation, and putting it onto a single bitmap so that at runtime you can actually take the individual frames out of that bitmap and essentially paste it into Flash, a bitmap data, and this was known as blitting, if you are creating a game using blitting. Well those same concepts apply when we are working with Canvas and now I am going to show you how you would incorporate an animation sprite sheet into your Canvas projects.
So what I want to do up here, is when we first come into the page, I want to load in that sprite sheet PNG. So what I am going to do is to create a variable called img = new Image; and I am going to set the source on that. So img.src is equal to sprite_sheet.png and this will immediately start loading that image in and then once the image has finished loading, I am going to listen for the onload event here which is going to fire as soon as my image has finished loading, and I am going to have it call a function called draw and this is the function that is going to be called repetitively to actually draw out my animation.
So the first thing I am going to do in the draw function is to call the requestAnimationFrame and pass in this draw function. And again, this is what will create our loop, and again, all of this is going to be started once our image has finished loading. So I need to first create some variables up here that I am going to need. So first thing I need to do is to keep a count of which frame I'm currently on, and I am going to call that variable count, and I'm going to set it initially to 0, because it's going to be at frame 0 when we first come into the animation.
And I am going to create two other variables, one called x and one called y, and that's going to hold the value for where in our big sprite sheet do we actually want to extract the pixels from. And we are going to be calculating that down in the draw function. Okay, so now I want to calculate that x and the y value. Well we can look at our sprite sheet, so let me actually go to the Desktop here, and open up that sprite sheet again, so we know some things about it, so we actually have nine animation frames across, and we also know that the total number of animation frames is 150.
So we can use that knowledge to write our code to extract the correct frame, so the first thing I want to do is to calculate the x position of where we want to extract that frame. So x is equal to, and now we're going to take that count variable, which tells us what frame number we are currently on, and we are going to use the modulus operator, which is essentially saying divide count by 9 and return what the remainder is when that happens. And I am going to multiply that value by 212, and the reason why is because each frame of the animation is actually 212 pixels wide by 201 pixels high, they're all the same exact size in the sprite sheet.
So this will actually give me the correct x position for where to pull out those pixels. So now we need to calculate the y value, so for the y value we are going to take the current count variable and divide it by 9, because essentially for each 9 frames across, we need to go another 201 pixels down on the y axis. So what I need to do, because this could obviously conceivably be a decimal number, I need to wrap that in the Math.floor function, and that will essentially round this value down that comes out.
Now this will give me essentially the row number, I need to now multiply that by the actual height of one of the frames, and that's 201 pixels high. So with these two lines I have essentially figured out, based on that count variable, where exactly the x and y position is for the frame that I need to extract. So to actually extract that image and display it, I am going to use the draw image function which we used in the last movie. So ctx.drawImage and first we pass in what image we actually want to draw into here.
Well that's the img variable, and now you to give the starting x and y position for what pixels we want to extract from the sprite sheet. Well that's those values that we just calculated for x and y. Now the width and height for how many pixels to extract, well, we know each frame is 212x201. Now the next thing we would say is where in our Canvas do we want to paste these pixels? Well we are just going to paste them at 0, 0.
And now lastly the width and height for essentially the scale, we are just going to put in the actual width and the height of the frame, which is to 212 and 201. So now we need to increment our count variable every time it comes into this. So for each new frame we need to increment count, but we need to make sure that we don't go over the number of frames that are available in the sprite sheet. So let's do a simple if statement here. We are going to say, if count is equal to 149, because remember, we are starting the count at 0 and there is 150 frames.
So if that's true, set count back to 0, else count++. So essentially if count is at the end of our frames, let's set it back to 0 so the animation loops again, if not, let's increment that count variable. So let's save it now, we will go over to the browser and refresh. Now you can see this is working, you can see our animation is playing the way that it should, but you will notice that we're not actually clearing the Canvas before the next frame, so all the frames are being drawn on top of one another, which can actually lead to some really cool effects, if you try to do kind of special effects.
But what we actually need to do is to clear that Canvas before we start drawing again, and to do that really come up right under the requestAnimationFrame and we are going the call the clearRect method of the Canvas context. So ctx.clearRect, and we can give a specific rectangle of the Canvas to clear. So in our case, we are going to start at 0, 0, an x and y of 0, 0, and we are just going to erase 212 pixels by 201 pixels, and again, that's the size of our actual animation.
There is no sense in clearing the entire 800x600 Canvas, because there's nothing been drawn on the other pixels. So now if I go back to the browser and refresh, we can see now we have our animation playing from our sprite sheet in a looping fashion, and there are actually some bubbles here, you can't really see because of the white background. But you can see now how you would go about implementing sprite sheet animation. Now it is worth noting that there is a lot of frameworks out there that will handle this for you.
There is one called Easel JS created by Grant Skinner, which I'll be talking about later in the course, which makes it really easy to incorporate things like sprite sheets. But again, to create a sprite sheet based animation, there is nothing more than embedding or drawing an image, you are just changing the image that's being drawn on every frame.
- Understanding HTML5 browser support
- Creating class files and animation loops
- Comparing Canvas and BitmapData
- Drawing dynamic graphics
- Exploring DOM animation
- Understanding CSS3 design properties
- Using CSS animations and transforms
- Understanding WebGL
- Using Adobe Edge and the CreateJS library