Sidequest

Drawing the Background

To draw the background, we need to leverage our sprite sheet and sprite map.

What is a Sprite Sheet?

If you aren't familiar with sprite sheets, they are a way to organize several images (sprites) into a single larger image. They're usually associated with some metadata that helps identify a sprite by its position and size within the sheet. It's common to see animations in a sprite sheet as well.

Here's a diagram to give you a better idea:

Sprite sheet diagram
Sprite sheet diagram

Background Sprite Metadata

To draw the background, we're going leverage the metadata object exported from the src/sprite-map.ts file. If you look in that file for the background property, you'll see that it contains information about the image location and size:

1
export const spriteMap = {
2
// ...
+
background: {
+
sourceX: 512,
+
sourceY: 0,
+
width: 512,
+
height: 512,
+
},
9
// ...
10
};

sourceX and sourceY are the coordinates of the top left corner of the sprite within the sprite sheet. width and height are the dimensions of the sprite.

This diagram should clear it up:

Frame diagram
Frame diagram

Drawing the Background Image

We're going to use the drawImage() method of the CanvasRenderingContext2D to render our image to the canvas. drawImage() has an overload that suits our needs perfectly.

Add the following code to main.ts to render the background:

1
import spriteSheetUrl from "#/assets/image/spritesheet.png";
2
import { config } from "#/config";
3
import { loadImage } from "#/lib/asset-loader";
+
import { spriteMap } from "#/sprite-map";
5
+
// Draw the background
+
context.drawImage(
+
spriteSheet,
+
spriteMap.background.sourceX,
+
spriteMap.background.sourceY,
+
spriteMap.background.width,
+
spriteMap.background.height,
+
0,
+
0,
+
spriteMap.background.width,
+
spriteMap.background.height
+
);

The first argument of this call is the image we want to sample. It's our source.

The next four arguments of the drawImage() call line up nicely with the diagram above. They describe how we're going to sample the image from the sprite sheet.

The last four arguments of the drawImage() call are the destination related arguments. Our destination here is the canvas. The first two are the x and y position of the top left corner of where we intend to place the image on the canvas. The last two are the destination width and height. It's common for the source and destination width/height to be the same.

Don't mind the gap on the bottom of the canvas. This will get filled once we render the ground.