Sprite Animation
A walking character or a spinning coin is not a video; it is a handful of still images shown in sequence, fast enough to read as motion. Those images usually live together in one file called a spritesheet, and animating them means drawing the right slice at the right time. This article covers spritesheets, drawing a single frame, and timing the frames so animation runs at a steady pace independent of frame rate.
It builds directly on canvas 2D rendering and the timing ideas from the game loop.
What you'll learn
What a sprite is
The word covers both the image and the moving object it represents.
Images that move
A sprite is a small image drawn onto the game world, such as a character, an enemy, or an item. Animating a sprite means swapping which image is shown over time, so a run cycle is a few frames of a character in different poses, displayed one after another. The illusion of movement is the same one the game loop relies on, applied to a single object.
Spritesheets explained
Loading dozens of separate image files is slow, so frames are packed together.
One image, many frames
A spritesheet is a single image containing many frames laid out in a grid. Loading one file instead of many is faster and simpler, and each frame is found by its row and column. If each frame is sixty four pixels wide, the third frame starts at an x offset of one hundred twenty eight pixels. This packing is also kinder to memory and the network.
Drawing one frame
The canvas can copy just a slice of an image, which is exactly what a spritesheet needs.
The nine argument drawImage
// drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)
var fw = 64, fh = 64; // frame size
var sx = frameIndex * fw; // source x in the sheet
ctx.drawImage(sheet, sx, 0, fw, fh, x, y, fw, fh);
The first four numbers after the image select the source rectangle, the frame, and the last four place it on the canvas. Changing frameIndex shows a different frame from the same sheet.
Timing the animation
Advancing a frame every loop would animate far too fast, so frames are timed.
Frames per second, not per frame
var timer = 0, frameIndex = 0, fps = 10;
function update(dt) {
timer += dt;
if (timer > 1 / fps) { // time for the next frame
frameIndex = (frameIndex + 1) % frameCount;
timer = 0;
}
}
Accumulating delta time and advancing only when enough has passed keeps the animation at a chosen speed regardless of how fast the game loop runs.
Animation states
A character does more than one thing, so it needs more than one animation.
Switching between animations
Most characters have several animations, idle, walking, jumping, each a range of frames on the sheet. The game picks the current animation from what the character is doing, which ties sprite animation to game state management. Switching cleanly, and resetting the frame index when the animation changes, keeps motion from glitching.
Common pitfalls
A few sprite mistakes are common at first.
What usually goes wrong
The most common is advancing a frame every loop, which animates too fast and varies by device; use a timer with delta time. The second is drawing before the spritesheet image has loaded, which shows nothing; wait for the image load event. The third is blurry sprites from the browser smoothing scaled pixel art, fixed by disabling image smoothing on the context. The drawing itself is covered in canvas 2D rendering.
Frequently Asked Questions
What is a sprite in game development?
A sprite is a small image drawn onto the game world, such as a character or item. Animating a sprite means swapping which frame is shown over time, so a run cycle is a few poses shown one after another.
What is a spritesheet?
A spritesheet is a single image holding many animation frames in a grid. Loading one file instead of many is faster and simpler, and each frame is located by its row and column position within the sheet.
How do I draw one frame from a spritesheet?
Use the nine argument form of drawImage. The four numbers after the image select the source rectangle, the frame, from the sheet, and the last four place it on the canvas. Change the source x to pick a different frame.
How do I control animation speed?
Accumulate delta time and advance the frame only when enough has passed, based on a frames per second value. This keeps the animation at a steady speed regardless of how fast the game loop runs.
Read next: handling game input, or the Game Development hub.