Learning Goals 3 min
By the end of this lesson you will be able to:
- Assemble a working three-level platformer by snapping together the cluster-G pieces you already built — arrow-key walking, gravity, jumping, on-ground checks, coin clones, patrolling enemies, and backdrop-based levels.
- Use a single level variable plus switch backdrop to to swap the whole world without spawning new sprites — same player, same enemies, new layout.
- Wire a complete game loop: collect 5 coins per level → touch the right edge → next level; touch an enemy → lose a life; R retries the current level from scratch.
Warm-Up — predict the pile 7 min
You've built eight separate sprites over the last cluster — the walker, the jumper, the gravity test, the coin clone spawner, the patrolling slime. None of them have ever lived in the same project. Today they all move in together. Before we wire them up, predict one piece.
when flag clicked
forever
if <key [right arrow v] pressed?> then
change x by (5)
end
if <key [left arrow v] pressed?> then
change x by (-5)
end
change y by (y-vel)
change [y-vel v] by (-1)
if <touching color [#00aa00] ?> then
set [y-vel v] to (0)
end
end
Click the flag. The player walks left/right fine. Press space — nothing jumps. Why? And what one line, added where, would let it jump?
Reveal the answer
There's no jump key script anywhere. The player falls (gravity is the change [y-vel v] by (-1) line) and lands (the touching-green check zeroes out the falling speed), but nothing ever pushes y-vel positive. To jump, you need one more if inside the forever:
if <<key [space v] pressed?> and <touching color [#00aa00] ?>> then
set [y-vel v] to (12)
end
The <> and <> matters — without the touching-green half, you'd be able to jump in mid-air forever. We'll come back to this combined check in Step 4.
Today we glue eight scripts like this one into a single playable game. No new blocks — just careful assembly.
New Concept — the full assembly map 15 min
A platformer isn't one big script. It's a handful of small ones, each on the right sprite, each watching the right thing. The trick is knowing which script lives where. Here's the map for today's build.
The sprites and their jobs
- Player — listens to arrow keys, holds y-vel, falls under gravity, jumps when on ground, loses a life when touching an enemy, advances the level when touching the right edge.
- Coin — one sprite, but on flag-click it makes five clones on the backdrop at fixed positions. Each clone deletes itself when the player touches it and adds 1 to score.
- Enemy (Slime) — patrols left and right between two x-positions. Doesn't do collision detection itself — the player handles that.
The variables and what they hold
- level — 1, 2, or 3. Picks which backdrop, which coin positions, which enemy patrol range.
- score — coins collected in the current level (0 to 5). Resets each level.
- lives — starts at 3. Game over at 0.
- y-vel — player's vertical speed. Negative = falling, positive = rising. Gravity adds
−1per frame.
The three backdrops
Paint three backdrops in the Backdrops tab: level-1, level-2, level-3. Each has green platforms (#00aa00) at different heights. The player walks on green. Anywhere else, gravity wins.
when I receive [start-level v]
switch backdrop to (join [level-] (level))
go to x: (-200) y: (0)
set [y-vel v] to (0)
set [score v] to (0)
The whole-game flow
The flag-click handler kicks off level 1. Each piece talks to the others through three broadcasts:
- broadcast [start-level v] — fires at flag and after every level advance. Resets player, score, coins, and enemies.
- broadcast [coin-grabbed v] — fires when a coin clone is touched. The score sprite (or just a variable watcher) updates.
- broadcast [game-over v] — fires when lives hits 0. Switches to a "Game Over" backdrop and stops the gated scripts.
Worked Example — building the mini platformer 35 min
Open Scratch. New project. We'll build in order: variables → backdrops → player → coins → enemy → level switch → retry. Ten steps.
Step 1 — Create the variables
Variables palette → Make a Variable. Create four for all sprites: level, score, lives, y-vel. Tick the watchers for score and lives; untick the rest.
Step 2 — Paint three backdrops
Stage → Backdrops tab. Make three new backdrops named exactly level-1, level-2, level-3. On each, paint flat green platforms (colour #00aa00) at different heights — level 1 is easiest, level 3 has gaps to jump. Add a fourth backdrop called game-over with big "GAME OVER" text. Names must match the join in Step 6.
Step 3 — Player: walk left and right
Pick a small sprite for the player (the gobo works well). On the player sprite, add this script:
when flag clicked
set [lives v] to (3)
set [level v] to (1)
broadcast [start-level v]
forever
if <key [right arrow v] pressed?> then
change x by (5)
end
if <key [left arrow v] pressed?> then
change x by (-5)
end
end
Flag it. The player slides left and right. No gravity yet — it just floats. That's fine.
Step 4 — Gravity, ground, and jump
Add a second forever loop on the same player sprite (yes, two foreverves on one sprite is fine — they run in parallel):
when flag clicked
forever
change y by (y-vel)
change [y-vel v] by (-1)
if <touching color [#00aa00] ?> then
set [y-vel v] to (0)
change y by (1)
end
if <<key [space v] pressed?> and <touching color [#00aa00] ?>> then
set [y-vel v] to (12)
end
end
The change y by (1) after landing nudges the player just off the green so gravity can pull again next frame — it stops a buzzing-on-the-floor glitch. Flag it. The player falls, lands, jumps with space.
Step 5 — The start-level handler
Add a third script to the player. This is what every level start (and every retry) calls:
when I receive [start-level v]
switch backdrop to (join [level-] (level))
go to x: (-200) y: (0)
set [y-vel v] to (0)
set [score v] to (0)
Flag again. The cat starts at left, score resets to 0, the backdrop is level 1.
Step 6 — Coin sprite with five clones
Add a small Coin sprite (the "Ball" works, or paint a yellow circle). On the coin:
when I receive [start-level v]
delete this clone
when I receive [start-level v]
hide
repeat (5)
create clone of [myself v]
wait (0.05) seconds
end
when I start as a clone
show
go to x: (pick random (-200) to (200)) y: (pick random (-100) to (100))
forever
if <touching [Player v] ?> then
change [score v] by (1)
broadcast [coin-grabbed v]
delete this clone
end
end
Step 7 — The patrolling enemy
Add an Enemy sprite (Slime, or anything). On the enemy:
when I receive [start-level v]
go to x: (0) y: (-100)
point in direction (90)
forever
move (3) steps
if on edge, bounce
end
Step 8 — Player loses a life on enemy touch
Add a fourth script to the player:
when flag clicked
forever
if <touching [Enemy v] ?> then
change [lives v] by (-1)
if <(lives) = (0)> then
broadcast [game-over v]
stop [all v]
end
broadcast [start-level v]
end
end
Touching the enemy costs a life and restarts the current level. Zero lives ends the game.
Step 9 — Advance level on right edge (with 5 coins)
Add a fifth player script:
when flag clicked
forever
if <<(x position) > (230)> and <(score) = (5)>> then
change [level v] by (1)
if <(level) > (3)> then
switch backdrop to [game-over v]
say [You Win!] for (3) seconds
stop [all v]
end
broadcast [start-level v]
end
end
The compound check matters: right edge alone isn't enough — you need all 5 coins first.
Step 10 — Retry the level on R
Add a Stage script (or a sixth player script):
when [r v] key pressed
broadcast [start-level v]
The whole game, one diagram
when flag clicked
set [lives v] to (3)
set [level v] to (1)
broadcast [start-level v]
forever
if <key [right arrow v] pressed?> then
change x by (5)
end
if <key [left arrow v] pressed?> then
change x by (-5)
end
end
What you just built: a complete game with three levels, gravity, jumping, coin collection, enemies, lives, a win screen, and a retry key. Every block in it came from earlier cluster-G lessons. The whole skill of this lesson is assembly — knowing which sprite each script lives on, and which broadcast wires them together.
Try It Yourself — three platformer extensions 15 min
Goal: Add a level watcher to the Stage so the player can always see which level they're on. Then change the player's costume per level — costume 1 on level 1, costume 2 on level 2, costume 3 on level 3.
when I receive [start-level v]
switch costume to (level)
Think: No new logic. You're reusing the same variable for two jobs (level number and costume number). That's a small example of a much bigger habit: re-using variables instead of inventing new ones.
Goal: Add a second enemy that patrols a different range. The catch: don't duplicate the enemy sprite — use clones. The original enemy makes one clone at flag, and the clone patrols at a different y-position.
when I receive [start-level v]
create clone of [myself v]
go to x: (-100) y: (-100)
point in direction (90)
forever
move (3) steps
if on edge, bounce
end
when I start as a clone
go to x: (100) y: (50)
point in direction (-90)
forever
move (4) steps
if on edge, bounce
end
Think: The player's touching [Enemy v]? check already covers the clone — Scratch's touching block treats every clone of a sprite as that sprite.
Goal: Add a checkpoint flag (a new sprite) at the middle of each level. If the player touches the flag, the retry handler (the R key) should respawn the player at the checkpoint instead of the left edge. Hint: add a checkpoint-x variable and read it in the start-level handler.
when flag clicked
set [checkpoint-x v] to (-200)
when I receive [start-level v]
switch backdrop to (join [level-] (level))
go to x: (checkpoint-x) y: (0)
set [y-vel v] to (0)
set [score v] to (0)
go to x — now reads the checkpoint variable. Reset checkpoint-x to −200 at the start of each new level.Think: One variable replaces what would have been a tangle of "if level = 1 go to x = −200, if level = 2…". This is the same pattern as level-driven costume switching in the Easy task — one variable, many uses.
Mini-Challenge — Faiz's coin counter 5 min
"Why won't level 2 start?"
Faiz finishes level 1 — collects all 5 coins, walks to the right edge. The level number ticks up to 2. The backdrop swaps. The player teleports back to the left. But the score watcher still says 5, and the moment Faiz touches the right edge of level 2 (without collecting anything), the game jumps straight to level 3. Here's his start-level handler:
when I receive [start-level v]
switch backdrop to (join [level-] (level))
go to x: (-200) y: (0)
set [y-vel v] to (0)
What's missing — and why does it cause the level-2 skip?
Reveal one valid solution
The handler never set [score v] to (0). After level 1, score is still 5 — and the level-advance check is <(x position) > (230)> and <(score) = (5)>. Both halves are true the moment the player nudges past x = 230 on level 2, so the game thinks "all 5 collected!" and bumps the level again.
The one-line fix:
when I receive [start-level v]
switch backdrop to (join [level-] (level))
go to x: (-200) y: (0)
set [y-vel v] to (0)
set [score v] to (0)
This is a classic forgot-to-reset bug. Anything a level uses that changes during play (score, y-vel, position, costume) must be re-initialised in the start-level handler — otherwise yesterday's state leaks into today's level.
Recap 3 min
You assembled a complete mini platformer: three levels driven by a level variable and one switch backdrop to; gravity and jumping driven by a y-vel variable and a green-ground colour check; five coin clones per level that delete themselves on touch; an enemy that patrols and costs a life on contact; a win path through right-edge + score-5; a retry on R. The whole game is six scripts on the player, three on the coin, one on the enemy, and one on the Stage. The hard part wasn't any single block — it was the wiring: which sprite holds which script, which broadcast wakes which handler, what gets reset and when.
- Capstone
- A project that combines several earlier lessons into one working whole. SCR-L03-43 is the cluster-G capstone — every block came from L03-29 through L03-42.
- Game loop
- The forever loop on the player that reads input, updates physics, and checks for win/lose conditions every frame. Today's player has two game loops running in parallel — one for input, one for gravity.
- Broadcast wiring
- The pattern of using broadcast + when I receive to wake up every relevant script at once. Today's
start-levelfires on every level start and every retry — one signal, six handlers. - Reset handler
- A script wired to a start signal whose only job is to put a sprite back into a known state — position, costume, variables, clones cleared. Forgetting one variable here is the #1 source of "weird leftover" bugs.
- Compound check
- A boolean built from two smaller booleans with <> and <>. The win check (right edge AND score = 5) and the jump check (space AND on-ground) are both compound checks.
Homework 2 min
Make it yours. Take today's project and polish one full pass.
- Re-paint each backdrop so the three levels feel different — a city, a jungle, a cave. Keep the platforms green (
#00aa00) so the gravity check still works. - Replace the 5 random-position coin clones with 5 fixed positions per level. Use an if <(level) = (1)> then chain inside the clone-spawn loop.
- Add a sound. Pick one: a jump sound on space, a coin-collect sound when a clone is deleted, or a "ouch" when a life is lost.
- Save as
HW-L3-43-Mini-Platformer.sb3.
Bring back next class:
- The
.sb3file. - A one-sentence note: "The hardest bug I hit was ___ and I fixed it by ___."
Heads up for next class: SCR-L03-44 moves us into cluster H — Build, Reflect, Recap. We'll build a 10-question trivia quiz that stores your top-5 high scores in a list. Different genre, but the same skill — gluing earlier pieces together into a complete experience.