Learning Goals 3 min
By the end of this lesson you will be able to:
- Use touching color [#000000] ? from the Sensing palette to detect when a sprite has stepped onto a black wall pixel.
- Build the move-then-undo pattern — change x or y, check the colour, undo the change if touching — across four separate when [arrow v] key pressed hats.
- Explain why a player sprite must contain no pure-black pixels, and either pick a coloured sprite or paint over the black bits before the script works.
Warm-Up — predict the wall-walker bug 7 min
You painted a maze last lesson — black walls, green start, red end. Today you'll teach a sprite to walk inside it. But first: what's the simplest broken version?
Adam tries this on the cat sprite, placed inside his maze:
when [right arrow v] key pressed
change x by (5)
What happens when Adam holds the right arrow against a black wall?
Reveal the answer
The cat walks straight through the wall. change x by (5) moves the cat 5 pixels to the right whether anything is in the way or not. Scratch motion blocks don't know about walls. They don't know about the backdrop. They don't know about anything except moving the sprite by the requested amount.
The fix is to move first, check second, and undo the move if you ended up inside a wall. Sounds clumsy — it is — but it works perfectly and it's only one extra line per direction.
Today's pattern adds exactly two more blocks per arrow key. After this lesson Adam's cat respects every wall in the maze.
New Concept — move, check, undo 15 min
Real game engines have "collision systems" that prevent you from moving into a wall in the first place. Scratch doesn't. Scratch lets you move wherever you ask, and gives you sensing blocks to notice after the fact. So the pattern is: take the step, then peek at your feet, then step back if you landed somewhere illegal.
The colour sensor
In the Sensing palette, scroll down to touching color [] ?. The colour swatch starts as some random shade — click it. A colour picker pops up with a saturation slider, brightness slider, and an eyedropper icon at the bottom. Click the eyedropper and then click any black pixel on your maze backdrop. The swatch now reads #000000.
if <touching color [#000000] ?> then
say [Wall!] for (0.2) seconds
end
The move-then-undo pattern
The trick is using opposite motion blocks: if you moved +5, you undo with -5. Same axis, same amount, opposite sign:
when [right arrow v] key pressed
change x by (5)
if <touching color [#000000] ?> then
change x by (-5)
end
Why is this OK to do? Because Scratch runs the whole script between frames. The user never sees the "inside the wall" moment — only the final position. Visually, the sprite just refuses to enter the wall.
One script per direction
You need four of these scripts — one for each arrow key. Each one moves on a different axis or sign:
- Right arrow: change x by (5), undo with change x by (-5).
- Left arrow: change x by (-5), undo with change x by (5).
- Up arrow: change y by (5), undo with change y by (-5).
- Down arrow: change y by (-5), undo with change y by (5).
Four little hats. Each one's undo block is the exact opposite of the move block. If you remember "undo is the negative", you've got the whole lesson.
The black-pixel rule for player sprites
Here's the trap: touching color [#000000] ? asks "is any pixel of me touching that colour on anything else". If the player sprite itself has any black pixels in its costume, the answer is always true — the sprite is touching its own black, even on a blank backdrop. The player can't move at all.
Worked Example — drop a player into your maze 12 min
Open the maze project from L03-32. We'll add a player in eight steps.
Step 1 — Pick a player sprite
Click Choose a Sprite in the sprite panel. Pick something colourful with no black outlines — Ball (the blue one) or Pico works well. Avoid the default Cat for now (those black whiskers and outlines are exactly the problem we warned about).
Step 2 — Shrink the player
The new sprite is probably too big to fit in your maze corridors. In the sprite info panel, set Size to about 30. It should be small enough to fit in the narrowest gap of your maze with room to spare.
Step 3 — Set the spawn position
Drag the player on the Stage to your green start square. Note the coordinates that appear in the sprite panel — say x: -200, y: -150. We'll lock it there on flag click:
when flag clicked
go to x: (-200) y: (-150)
switch backdrop to [Maze1 v]
Step 4 — Right arrow
From Events: when [right arrow v] key pressed. From Motion: change x by (5). From Control: if <> then. From Sensing: touching color [#000000] ? — and use the eyedropper to grab true black from your maze wall. From Motion again: change x by (-5) inside the if-then.
when [right arrow v] key pressed
change x by (5)
if <touching color [#000000] ?> then
change x by (-5)
end
Step 5 — Left arrow
Right-click the right-arrow stack → Duplicate. Change the hat dropdown to left arrow, both change x values to -5 and 5 (the opposite of right).
when [left arrow v] key pressed
change x by (-5)
if <touching color [#000000] ?> then
change x by (5)
end
Step 6 — Up arrow
Duplicate again. Change the hat to up arrow, and replace both change x blocks with change y at 5 and -5.
when [up arrow v] key pressed
change y by (5)
if <touching color [#000000] ?> then
change y by (-5)
end
Step 7 — Down arrow
Last one. Duplicate, change hat to down arrow, flip the y values:
when [down arrow v] key pressed
change y by (-5)
if <touching color [#000000] ?> then
change y by (5)
end
Step 8 — Click the flag and play
Hit the green flag. The player drops onto the green square. Hold the right arrow — the player slides smoothly until it bumps a wall, then refuses to move further. Try every direction. Try diagonal moves (hold two arrows). Try the dead-ends. Every wall holds.
What you just built: the same wall-collision pattern that runs every top-down RPG ever made — Pokémon, Stardew Valley, Hades, Zelda. The grown-up versions use tile maps and AABB checks, but the idea is identical: try the move, see if it's invalid, snap back if it is.
Try It Yourself — three wall-collision drills 12 min
Goal: Add a "you win" message. When the player reaches the red end square, say [You win!] for (2) seconds. Use touching color [#ff0000] ? — eyedropper the red end square.
when flag clicked
forever
if <touching color [#ff0000] ?> then
say [You win!] for (2) seconds
stop [all v]
end
end
Think: The same colour-sensing trick that detects walls now detects the goal. One block, different colour, different reaction. L03-34 will swap to a finish-line sprite for more interesting endings.
Goal: Make the player rotate to face the direction they're moving. When pressing right, point in direction (90). When pressing left, -90. Up, 0. Down, 180. Add the point-in-direction before the change-x/y in each handler.
when [right arrow v] key pressed
point in direction (90)
change x by (5)
if <touching color [#000000] ?> then
change x by (-5)
end
Think: Set the sprite's rotation style to left-right from the sprite info panel if you don't want the sprite flipping upside-down on the down arrow. (Sprite panel → the small arrows icon → middle option.)
Goal: Add a step counter. Make a variable steps, start at 0 on flag click, and change [steps v] by (1) every time the player successfully moves (i.e. not inside the undo branch). When the player reaches the red goal, the score appears.
when [right arrow v] key pressed
change x by (5)
if <touching color [#000000] ?> then
change x by (-5)
else
change [steps v] by (1)
end
Think: The else branch on if-then is where "the move worked" lives. Anywhere the undo doesn't fire, the player legitimately took a step. This is how speedrun timers, energy systems, and stamina meters get wired into top-down games.
Mini-Challenge — the cat that can't move 5 min
"Tasha's frozen cat"
Tasha follows the worked example exactly — but uses the default Cat sprite instead of Pico. She hits the flag and the cat appears on the green start square. She presses every arrow key. The cat doesn't move at all. Not a pixel.
She shows you her right-arrow script. It's identical to yours:
when [right arrow v] key pressed
change x by (5)
if <touching color [#000000] ?> then
change x by (-5)
end
The colour swatch is true black. The maze is fine. What's stopping the cat from moving?
Reveal one valid solution
The default Cat sprite has black outlines around its body, ears, mouth, and whiskers. touching color [#000000] ? doesn't care which black pixels are touching — it only cares that they are. The cat's own black whiskers are touching its own black outline, so the answer is always true, even on a blank backdrop. Every move gets undone before the player ever sees it.
Two valid fixes:
- Pick a different sprite with no black pixels (Pico, Ball, Beetle, Star — most non-cat sprites are fine).
- Repaint the cat. In the Costumes tab, use the fill bucket to repaint the black outlines a different dark colour (very-dark-grey
#202020is close enough visually but doesn't trigger the check). Do this for every costume, not just the first.
This is the single most common Cluster F bug. Black walls in the backdrop demand that no other sprite contains black.
Recap 3 min
You met the move-then-undo pattern. Four arrow-key hats, each one moving the player by 5 pixels and then asking touching color [#000000] ?; if the answer is true, the move gets undone with the opposite-sign motion block. The walls live in the backdrop, the script lives on the player, and as long as the player sprite contains no black pixels of its own, every wall in every maze you draw automatically works. This is the same pattern under the hood of every top-down game you've ever played.
- Touching colour
- The Sensing reporter touching color [] ? — reports true when any pixel of this sprite is on top of any pixel of the specified colour, anywhere on the Stage (backdrop or other sprites).
- Move-then-undo
- The standard Scratch pattern for wall collision: change x/y by N, check the wall colour, and if touching, change x/y by -N to snap back. Three blocks per direction.
- Eyedropper
- The pipette icon at the bottom of Scratch's colour picker. Click it then click any pixel anywhere in the editor to copy that exact colour into the swatch — the only reliable way to pick true
#000000. - Movement step
- How many pixels the player moves per arrow-key press. Must be smaller than the wall thickness (we use 5, walls are 8-10) or the player jumps over walls.
- Sprite costume bleed
- The bug where a sprite's own pixels trigger its own colour-sensing check, freezing all movement. Fixed by choosing a sprite without those pixels, or repainting them away.
Homework 2 min
Wire up your three mazes. Open the homework project from L03-32 (three maze backdrops). Add the player and the four arrow-key scripts.
- Pick a player sprite with no black pixels. Shrink it to size
30. - Add the four when [arrow v] key pressed stacks — move-then-undo for each direction, 5 pixels.
- On green flag, the player goes to the green start square of whichever maze is currently shown.
- Add a number key to switch mazes mid-game: when [1 v] key pressed → switch backdrop to [Maze1 v] + go to start. Repeat for keys 2 and 3.
- Save as
HW-L3-33-MazeWalker.sb3.
Bring back next class:
- The
.sb3file. All three mazes should be walkable with no wall-tunneling. - Your answer to: "What happens if you change the movement step from 5 to 20? Try it. Did the player jump through any walls? Which ones?"
- Your fastest solve time for
Maze3(use a stopwatch or count Mississippis).
Heads up for next class: SCR-L03-34 tightens up the wall-walker. We'll add screen-edge handling so the player can't escape the canvas, and clean up the diagonal-move stutter you might notice while holding two arrows at once.