Platformer-Final.sb3, and share it on scratch.mit.edu.Learning Goals 3 min
By the end of this Build lesson you will have:
- A three-level platformer with three backdrops, a working level variable, and a level loader that switches scenery and respawns content when the player advances.
- A complete player sprite combining the L04-17 gravity loop, on-ground detection, jumping, arrow-key movement, and edge-of-Stage screen wrapping to the next level.
- All of the level content from previous lessons integrated and gated by the level variable: coin clones spawned per-level, varied enemies per-level, a checkpoint sprite, the boss fight at the end of level 3, and the title + win + credits polish from SCR-L04-23 — wired together as one shareable project.
Warm-Up — what you already own 7 min
You've spent seven lessons (L04-17 through L04-23) building separate pieces of a platformer. Today you stop building new things and start assembling. Before you open Scratch, list everything you already have:
- L04-17 — Gravity + Jumping: the velocity-y variable, the falling loop, the on-ground check, the spacebar-jump.
- L04-18 — Coins: a coin sprite using create clone of (myself v) to spawn many copies, score variable, sound on pickup.
- L04-19 — Enemies: a patrol enemy that walks back and forth, broadcasts game-over on touch.
- L04-20 — Level Variable + Backdrops: a level number, three backdrops, a level-loader script that switches backdrops via broadcast.
- L04-21 — Checkpoints: a sprite that, when touched, sets checkpoint-x and checkpoint-y so the player respawns there instead of at the level start.
- L04-22 — Boss: a 5-HP boss with patrol/attack state machine, vulnerable only to stomp hits, broadcasts victory on defeat.
- L04-23 — Polish: title screen, end screen with score + play-time, scrolling credits, the game-start refactor.
Predict puzzle. Look at this level-loader script. What happens when the player walks off the right edge of the Stage in level 1?
when I receive (player-exited-right v)
change [level v] by (1)
if <(level) = (4)> then
set [level v] to (3)
end
broadcast (load-level v)
Reveal the answer
Walking off the right edge of level 1 increments level from 1 to 2, the level = 4 check is false, and broadcast (load-level v) tells the level loader to switch backdrops and respawn content. The cap at level 4 prevents the player from accidentally walking past level 3 and breaking the game — once level = 3, you can't go higher. This pattern (advance, clamp, broadcast) is the heart of today's assembly.
Today's hard part isn't writing new code. It's making seven separate things — each of which works on its own — cooperate. Most of the bugs will be timing: who runs first, who runs second, what variable was already set when a script started.
New Concept — the assembly map 15 min
A Build lesson doesn't introduce one block — it introduces a structure. Today's structure is the event chain that runs the whole game:
The event chain
- Flag click → Title sprite shows, everything else hides or stands still.
- Space pressed → Title hides, broadcasts game-start.
- game-start → Level loader sets level to 1, score to 0, play-time to 0, broadcasts load-level; player sprite shows and starts running its gravity+jump+move loop; play-time ticker starts.
- load-level → Backdrop switches, old clones (coins, enemies) get deleted, new ones get spawned for the new level. Player jumps to start position (or to the checkpoint if one was saved).
- player-exited-right (broadcast by the player when crossing the right edge) → Level loader increments level, re-broadcasts load-level.
- On level 3, end of room → Boss spawns. Player fights boss.
- Boss HP = 0 → Boss broadcasts victory.
- victory → End screen shows score and play-time, broadcasts show-credits.
- show-credits → Credits sprite scrolls up. Game over.
Nine broadcasts. Three backdrops. Six (or seven) sprites: Player, Coin, Enemy, Checkpoint, Boss, Title, EndScreen, Credits.
The level-loader pattern
Make a Stage script (not a sprite — the Stage itself can hold scripts). Its job is to listen for load-level and switch backdrop + spawn content based on the current level value:
when I receive (load-level v)
if <(level) = (1)> then
switch backdrop to (jungle v)
end
if <(level) = (2)> then
switch backdrop to (cave v)
end
if <(level) = (3)> then
switch backdrop to (volcano v)
end
broadcast (spawn-content v)
Gating clones by level
Each content sprite listens for spawn-content and decides for itself whether to spawn — based on the current level. The Coin sprite, for example:
when I receive (spawn-content v)
delete this clone
if <(level) = (1)> then
go to x: (-100) y: (-50)
create clone of (myself v)
go to x: (50) y: (-50)
create clone of (myself v)
end
if <(level) = (2)> then
go to x: (-150) y: (0)
create clone of (myself v)
end
The same pattern works for enemies — each level can spawn a different number, kind, or position. Level 3 spawns no regular enemies, only the boss (because spawn-content checks level = 3 and broadcasts start-boss-fight instead).
Where checkpoint fits in
The checkpoint sprite from L04-21 sets checkpoint-x and checkpoint-y when touched. The player's death-handler reads those variables on respawn:
when I receive (game-over v)
go to x: (checkpoint-x) y: (checkpoint-y)
set [velocity-y v] to (0)
Common assembly mistakes
Worked Build — assembling the full game in twelve steps 35 min
Open Scratch. You can start from a fresh project and copy-paste sprites from your earlier lesson files, or open your most complete L04-23 project and extend it. Either way works.
Step 1 — Import or recreate the three backdrops
Stage → Backdrops. Add three: jungle, cave, volcano. You can use Scratch library backdrops or paint your own. Make sure the bottom strip of each backdrop is a "floor" colour your gravity script can detect (or use a floor sprite — same idea).
Step 2 — Build the Player sprite
Bring in (or rebuild) the player from L04-17. Three scripts hatted on when I receive (game-start v): the gravity loop (forever change y by velocity, etc.), the arrow-key movement, and the spacebar-jump (only sets velocity-y to a positive number if on-ground). Test by pressing flag → space → arrow keys. The player should move and fall correctly.
Step 3 — Build the Stage's level-loader
On the Stage itself: a when I receive (load-level v) handler that switches backdrops by level and broadcasts spawn-content. Also a when I receive (game-start v) handler that sets level to 1, score to 0, play-time to 0, and broadcasts load-level. Test by pressing space — the backdrop should change to jungle.
Step 4 — Add the right-edge level-advance
On the Player: when I receive (game-start v) → forever → if x position > 230 then change level by 1, clamp at 3, broadcast load-level, go to x: (−200). Test by walking the player to the right edge — backdrop should switch.
Step 5 — Spawn coins per level
Bring in your Coin sprite from L04-18. Replace its old flag-click spawner with a when I receive (spawn-content v) handler that delete this clones first, then conditionally creates clones at hard-coded positions per level. Test by switching levels — coins should appear in the right spots and disappear when you change levels.
Step 6 — Add the score chain
On the Coin sprite, in the clone's behaviour script: if touching player, change score by 1, play a sound, delete this clone. Score should already exist as a variable. Test by walking onto a coin — score increases by 1, coin disappears.
Step 7 — Bring in the Enemies
From L04-19. Same spawn-content gating: enemies appear in level 2, no enemies in level 1 (easy intro level), and level 3 spawns the boss instead. When the player touches an enemy, broadcast game-over. Test by losing to an enemy on level 2.
Step 8 — Add the Checkpoint
From L04-21. The checkpoint sprite spawns at a fixed position in each level (gated by the level variable). When the player touches it, it sets checkpoint-x and checkpoint-y and hides itself. The Player's when I receive (game-over v) handler respawns at the checkpoint instead of the level start. Test by touching a checkpoint, dying, and confirming you respawn at the checkpoint.
Step 9 — Wire up the Boss to level 3
From L04-22. In the Stage's spawn-content handler, add: if level = 3 then broadcast start-boss-fight. The boss sprite responds, appears, and runs its three scripts (main loop, state switcher, stomp + win). Test by skipping to level 3 (or use the right-edge advance twice) and fighting the boss.
Step 10 — Bring in the Title, EndScreen, and Credits
From L04-23. The Title shows on flag-click and hides on space (broadcasting game-start). The EndScreen listens for victory and shows score + play-time. The Credits scroll up on show-credits broadcast. Test the full chain end-to-end.
Step 11 — Add sound and small visual polish
Pick three or four sounds from the Scratch library. start sound (coin v) on coin pickup, start sound (boom v) on enemy hit, start sound (cheer v) on victory, and maybe a backing music loop on the Stage that plays during gameplay. Sound is the smallest possible change that adds the largest amount of polish.
Step 12 — Test the full game three times
End-to-end test, then end-to-end test, then end-to-end test. Catch every glitch. Reset all variables, click flag, press space, play level 1 → 2 → 3 → boss → victory → end screen → credits. If anything breaks at any step, fix it and run the full chain again. This is the only way to know it actually works.
The full assembled stack — Stage level loader
when I receive (game-start v)
set [level v] to (1)
set [score v] to (0)
set [play-time v] to (0)
broadcast (load-level v)
when I receive (load-level v)
if <(level) = (1)> then
switch backdrop to (jungle v)
end
if <(level) = (2)> then
switch backdrop to (cave v)
end
if <(level) = (3)> then
switch backdrop to (volcano v)
end
broadcast (spawn-content v)
Player — gravity + jump + arrow-keys + level-advance + respawn
when I receive (game-start v)
show
go to x: (-200) y: (0)
set [velocity-y v] to (0)
forever
change [velocity-y v] by (-1)
change y by (velocity-y)
if <touching color [#000000] ?> then
change y by (1)
set [velocity-y v] to (0)
end
if <key [right arrow v] pressed?> then
change x by (5)
end
if <key [left arrow v] pressed?> then
change x by (-5)
end
if <<key [space v] pressed?> and <(velocity-y) = (0)>> then
set [velocity-y v] to (12)
end
if <(x position) > (230)> then
change [level v] by (1)
if <(level) > (3)> then
set [level v] to (3)
end
broadcast (load-level v)
go to x: (-200) y: (0)
end
end
when I receive (game-over v)
go to x: (checkpoint-x) y: (checkpoint-y)
set [velocity-y v] to (0)
Stage spawn-content gating (for boss on level 3)
when I receive (spawn-content v)
if <(level) = (3)> then
broadcast (start-boss-fight v)
end
What you just built: a complete, shareable game. Title → three levels → coin collection → enemies → checkpoint → boss → win screen → credits. Every piece is something you already understood; today you wired them together. Click See inside on any random platformer at scratch.mit.edu and you will find the same shapes you just used. This is what professional Scratch projects look like, and you built one.
Try It Yourself — three assembly drills 15 min
Goal: Add a fourth backdrop and a small "transition" message between levels. When the player advances from level 1 to level 2, the Stage briefly switches to a backdrop called level-loading for half a second, then to the next level's backdrop. Cheap-but-effective polish.
when I receive (load-level v)
switch backdrop to (level-loading v)
wait (0.5) seconds
if <(level) = (1)> then
switch backdrop to (jungle v)
end
if <(level) = (2)> then
switch backdrop to (cave v)
end
if <(level) = (3)> then
switch backdrop to (volcano v)
end
broadcast (spawn-content v)
Think: Pacing matters. A game that snaps instantly from one level to the next feels frantic; a game with a quarter-second pause feels intentional. Try removing the wait and feel the difference.
Goal: Add a lives system. The player starts with 3 lives. Touching an enemy costs 1 life (and respawns at the checkpoint) instead of immediately ending the game. Game over only when lives = 0. Show the lives count on the Stage.
when I receive (game-start v)
set [lives v] to (3)
when I receive (game-over v)
change [lives v] by (-1)
if <(lives) > (0)> then
go to x: (checkpoint-x) y: (checkpoint-y)
set [velocity-y v] to (0)
else
broadcast (final-game-over v)
end
GameOverScreen sprite that listens for final-game-over instead.Think: Lives turn enemies from "instant death" into "graduated penalty". This is a standard platformer pattern — Mario has it, Sonic has rings, every roguelike has HP. Same idea, different number.
Goal: Add a level-3-key requirement. The boss fight in level 3 doesn't start automatically — the player has to first collect a boss-key sprite hidden somewhere in level 3. Only then does picking it up broadcast start-boss-fight.
when I receive (spawn-content v)
hide
if <(level) = (3)> then
go to x: (100) y: (-50)
show
end
when flag clicked
forever
if <touching (Player v) ?> then
hide
broadcast (start-boss-fight v)
stop [this script v]
end
end
BossKey sprite. Spawns at a fixed position only in level 3, waits to be touched, then triggers the boss fight and stops listening so it can't fire twice.Think: One small gate turns "linear level 3" into "explore-and-find level 3". The boss key is the first hint of quest design — the idea that progress can require finding something, not just walking far enough. A massive design idea hiding in five blocks.
Mini-Challenge — the level that won't load 5 min
"Wei Han's broken level 2"
Wei Han assembled the whole game following the worked Build. Level 1 plays perfectly: jungle backdrop, coins spawn, no enemies, walk right, advance to level 2. But the moment level 2 loads, the backdrop changes to cave — and no enemies appear. The coins from level 1 are also still visible. Here are the relevant scripts:
when flag clicked
go to x: (-50) y: (-50)
hide
create clone of (myself v)
go to x: (100) y: (-50)
create clone of (myself v)
when I receive (spawn-content v)
if <(level) = (2)> then
go to x: (0) y: (-50)
show
forever
move (2) steps
if <touching (_edge_ v) ?> then
turn cw (180) degrees
end
end
end
What's wrong with each one, and why does the bug manifest the way it does?
Reveal one valid solution
Two separate Build mistakes.
Bug 1 — Coins. Wei Han kept the original L04-18 hat (when ⚑ clicked) for spawning coins. So coins spawn once, at the very beginning, in their level-1 positions, and never respawn. When level 2 loads, those level-1 clones are still floating in their old spots, and no new ones appear. Fix: hat on when I receive (spawn-content v) instead, and add a delete this clone at the top of the clone behaviour so old clones get wiped before new ones spawn.
Bug 2 — Enemies. Wei Han's enemy script has the right hat — but the enemy sprite is only one sprite, not a clone. The very first time spawn-content fires (on level 1), the script enters the level = 1 branch (which is missing — so it does nothing), but the script doesn't have a forever loop running outside the if. When level 2 fires, the script does enter the level = 2 branch, but immediately the if-block has a forever inside it, which means once the script enters that forever it will never leave to respond to another spawn-content broadcast. If you advance to level 3, the enemy keeps walking around like it's still in level 2.
The cleaner pattern: enemies should be clones too. Spawn-content kills old enemy clones, then creates new ones for the right level. Each clone runs its own forever.
when I receive (spawn-content v)
delete this clone
hide
if <(level) = (2)> then
go to x: (0) y: (-50)
create clone of (myself v)
end
when I start as a clone
show
forever
move (2) steps
if <touching (_edge_ v) ?> then
turn cw (180) degrees
end
if <touching (Player v) ?> then
broadcast (game-over v)
end
end
The rule: in a Build, anything that can vary by level should be spawned by clones, not by toggling visibility on a singleton sprite. Cleanup before respawn. Forever loops live in the clone's behaviour, not in the spawner.
Recap 3 min
You assembled a complete multi-level platformer. Three backdrops, a level variable, a Stage-based level loader, and content sprites that respawn themselves per level via the spawn-content broadcast. The player carries the gravity + jump + arrow + level-advance + respawn-at-checkpoint behaviour. Coins, enemies, the checkpoint sprite, and the boss all gate themselves on the level variable. The title + end screen + credits frame the game from outside. Every piece was a previous lesson; today's lesson was the structure that lets them cooperate. You have a real game. Upload it to scratch.mit.edu and ask people to play.
- Build lesson
- A lesson that assembles previous lessons rather than introducing new blocks. The hard part is structure and timing, not new syntax. Cluster D's Build is SCR-L04-24.
- Level loader
- A script (usually on the Stage) that listens for load-level, switches the backdrop based on the level variable, and broadcasts spawn-content so every content sprite can respawn itself.
- spawn-content
- A broadcast received by every content sprite (coins, enemies, checkpoint, boss). Each sprite reads the level variable and decides for itself what to do. Lets sprites self-manage instead of being centrally controlled.
- Event chain
- The sequence of broadcasts that runs the whole game: game-start → load-level → spawn-content → (gameplay) → start-boss-fight → victory → show-credits. Each broadcast triggers the next phase.
- Gating
- Wrapping a sprite's spawn or behaviour in
if (level) = (N) then ...so it only activates on the correct level. The pattern that makes one project handle three different levels. - End-to-end test
- Playing the entire game from flag-click to credits without stopping, to confirm every wire works. The only test that catches integration bugs.
Homework 2 min
The Share Drill. Take your assembled game from this lesson and prepare it for sharing.
- Save the project as
HW-L4-24-My-Platformer.sb3. - Open the Scratch website (scratch.mit.edu), sign in, and upload the project.
- Write a short project description: what the game is, controls (arrow keys + space + space to start), and any credits.
- Set the project to Shared (the button is on the project page).
- Send the link to two people — a parent, a sibling, a classmate — and ask them to play it once without you helping. Watch where they get stuck.
Bring back next class:
- The shareable Scratch URL.
- Your answer to: "Where did each of your two playtesters get stuck or confused? Was it the same place? What's the smallest change you could make next class to fix the most common one?"
- The
.sb3file as a backup, in case Scratch goes down.
Heads up for next class: SCR-L04-25 opens the final cluster of Level 4 — the Music extension. You'll set Scratch aside as a platformer engine for a few lessons and use it to compose tunes with notes, instruments, and tempos. A complete change of pace after the seven-lesson platformer Build. Bring your shared link to next class — we'll play each other's games as a warm-up.