Lesson 4 of 4
A Camera That Follows
The world is now wider than the screen. You move the view instead of the player.
What you will learn
- World and screen positions
- ctx.save and ctx.restore
- ctx.translate
- Limiting the camera
- A deadzone
Before you start
Platforms and Collisions. The level now goes past the right edge of the canvas.
What this stage does
Walk to the right. The view follows you. Walk back to the start and the view stops at the edge of the world. Jump high and the view moves up. It only moves after you leave the middle of the screen.
Two sets of positions
| Name | What it means |
|---|---|
| World position | Where a thing really is. The world is 2000 wide. A platform at x: 1500 is always at 1500. |
| Screen position | Where a thing appears on the 800 pixel canvas. |
The camera is the difference between the two. camera.x and camera.y say where the bottom-left corner of the screen sits in the world. The screen is just another rectangle. The camera costs three lines in draw(). Everything drawn between save() and restore() is shifted by the camera. Everything drawn outside them stays still. That is what you want for a sky.
// Sky first, not shifted, so it never scrolls
ctx.fillStyle = "skyblue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.translate(-camera.x, camera.y);
// ...draw the platforms and the player at their WORLD positions...
ctx.restore(); // put the camera back, ready for the next frameLeft and right: centre, then limit
// Try to keep the player in the middle of the screen
camera.x = player.x + player.width / 2 - canvas.width / 2;
// Do not scroll past either edge of the world
if (camera.x < 0) camera.x = 0;
if (camera.x > worldWidth - canvas.width)
camera.x = worldWidth - canvas.width;Without the two limits, you walk to the start of the level and see empty space beside the world. This is the same two-line pattern from stage 1. There you kept the player on screen. Here you use it on the view.
Up and down: the deadzone
You could centre the view up and down as well. Then the view jumps on every hop. That is unpleasant to play. Instead, the camera only moves when the player leaves a band in the middle of the screen. deadzoneY is how tall that band is, above and below the centre. Small hops do not move the view. Climbing high pulls the view along.
The camera's numbers
Set the deadzone to 0 and jump. The view lurches on every jump. Put it back to 80 and jump again.
How far you can move up or down before the view follows. Set it to 0 and jump. That is the version with no deadzone.
How far right you can walk before the view stops.
Jump high enough to push past the deadzone.
const playerMiddleY = player.y + player.height / 2;
const screenMiddleY = camera.y + canvas.height / 2;
// Went above the band: pull the camera up
if (playerMiddleY > screenMiddleY + camera.deadzoneY) {
camera.y = playerMiddleY - canvas.height / 2 - camera.deadzoneY;
}
// Went below the band: push the camera down
if (playerMiddleY < screenMiddleY - camera.deadzoneY) {
camera.y = playerMiddleY - canvas.height / 2 + camera.deadzoneY;
}
// Do not scroll below the bottom of the world.
// The sky above has no limit, so there is no top edge to stop at.
if (camera.y < 0) camera.y = 0;The left edge of the world is 0. The bottom of the world is 0 too. Both limits are the same line of code with a different letter in it.
Build it step by step
Make the world too big
Add platforms past
x: 800and setworldWidthto 2000. Change the player's limit fromcanvas.widthtoworldWidth. Play. You can walk off the right of the screen and vanish. The level is there. You just cannot see it.Move the view by hand
Add
const camera = { x: 0, y: 0 }. Add thesave,translate, andrestorelines todraw(). Setcamera.x = 400by hand and reload. The world slides across. Nothing follows the player yet. You can still see how it works.Follow the player
Replace your hand-set value with the centring line in
update(). The view now follows you. It also scrolls past the ends of the world.Limit the camera
Add the two
ifstatements for left and right. Walk to both ends and check that the view stops.Add vertical follow, twice
First set
camera.ywith the same centring line you used forcamera.x. Jump. The whole screen lurches every time. Now replace that line with the deadzone version. Jump again. Trying both versions teaches you more than any explanation.
Try these changes
Make these changes in the files beside this guide. Each one only uses what this lesson has already covered. Tick each one when it works.
Check yourself
Three quick questions on this lesson. Get them all right to finish the lesson and earn a pack.
Loading your answers
Teacher's versionHow to run this lesson, what to check, and any answers. Students do not need this.
How to teach it
- Slow down on step 2. Setting
camera.xby hand separates two questions. One is "what does translate do". The other is "how does following work". Students get lost when you teach both at once. - The signs confuse almost everyone. Stand at the board and move a piece of paper left. As you move it, say "the camera went right". Students learn from the gesture faster than from an explanation. Do the same gesture upward for the up and down camera. That one uses a plus sign because
drawRecthas already turned the picture over. - Do step 5 in the wrong order on purpose. A camera that lurches feels unpleasant within two jumps. The student then asks for the deadzone themselves.
- Draw the deadzone as a horizontal band on the board. Mark the player inside it, above it, and below it. The two
ifstatements match that picture exactly.