Learning Goals 3 min
By the end of this lesson you will be able to:
- Use single-stepping — clicking a stack one block at a time in the Script Area — to watch what each block actually does on the Stage.
- Drop a temporary say ((variable)) for (1) seconds into a stack as a print-debug to peek at a number mid-script.
- Slow a runaway forever loop down with wait (1) seconds so you can see the bug happen instead of guessing.
Warm-Up — Aisyah's missing meow 7 min
Aisyah built a "catch the kuih" game last weekend. She wanted the cat to meow every time the score reached a multiple of 5. She wrote this stack on the cat, snapped it under a when flag clicked, and hit the flag.
when flag clicked
set [score v] to (0)
forever
change [score v] by (1)
if <(score) = (5)> then
play sound [Meow v] until done
end
end
Why does the meow happen exactly once and then vanish forever?
Reveal the answer
The () = () question only reports true when score is exactly 5. Score 6, 7, 8 … 15, 16 are all not equal to 5. Aisyah really wanted "score is a multiple of 5" — a different question entirely (it uses () mod (), which she'll meet in L02-08). But she can't see this just by staring at the blocks. She needs a way to watch the score while the loop runs.
Today is about the three Scratch moves that turn "it doesn't work" into "I can see exactly where it breaks": single-step, print, slow down.
New Concept — three ways to spy on a stack 15 min
A bug is not a moral failing. It's just a script doing something different from what you pictured. Debugging is the skill of seeing what the script is actually doing instead of what you wish it were doing. Scratch gives you three friendly tools.
1. Single-stepping — click each block by hand
In the Script Area (the middle panel), you can click any individual block to run just that block. The block flashes yellow and you see its effect on the Stage immediately. Click move (10) steps — the cat shuffles 10 pixels. Click say [Hello!] for (1) seconds — the bubble appears.
You can also click a whole stack. Scratch runs it from the top. The trick: with a stack that contains a forever loop, clicking the stack will start the loop running in the background — click the stack a second time to stop it.
move (10) steps
turn cw (15) degrees
say [Step taken!] for (1) seconds
Single-stepping is brilliant for "does this one block do what I think it does?" questions. It's less useful inside a forever loop, because the loop runs too fast to watch.
2. Print-debug with say ((variable))
The cat can tell you what's inside a variable. Drop a say ((score)) for (1) seconds into the middle of a loop and the cat will hold up a speech bubble with the current value every time around. Even better — you can drop several says into different spots to see where the value changes.
when flag clicked
set [score v] to (0)
forever
change [score v] by (1)
say (score) for (1) seconds
end
This is the single most useful debugging trick in Scratch. If a variable's value surprises you, the say block shows you the truth. When you've finished debugging, you delete the say — it was scaffolding, not part of the real script.
You can also tick the checkbox next to a variable in the Variables palette to show its watcher in the corner of the Stage. The watcher updates live — no say needed. Use the watcher for "I want to see this value continuously"; use the say for "I want the cat to announce it at this exact point in the script".
3. Slow the loop down with wait
A forever loop runs about 30 times a second. Most bugs happen too fast for human eyes. Drop a wait (1) seconds inside the loop — now it cycles once a second and you can watch each pass.
when flag clicked
forever
move (10) steps
if <touching [edge v] ?> then
turn cw (180) degrees
end
wait (1) seconds
end
One second is dramatic — try 0.2 for a milder slow-down. Like the say block, the wait is debug-only. Remove it when you're done.
The four bug families you'll meet most
- Typo in a broadcast name. You broadcast
start-gamebut the receiver listens forstart_game. The dash and the underscore look the same. Result: silence. - Wrong dropdown choice. You meant touching [edge v]? but accidentally selected touching [Sprite1 v]?. The block looks the same.
- Missing forever. A bare if-then runs once at the flag click and never again. Half the "my key press does nothing" bugs are a missing forever.
- Off-by-one in a repeat. repeat (10) runs the body 10 times, not 11. If you want 10 dance moves and a final pose, the pose lives outside the repeat.
Worked Example — debugging Daniel's catch-the-kuih 12 min
Daniel built a tiny catch game. A kuih sprite drops from the top, the player moves the cat with arrow keys, and the score should go up by 1 every time the cat catches the kuih. He hits the flag — nothing scores. The kuih falls. The cat catches it. The score stays at 0.
when flag clicked
set [score v] to (0)
go to x: (0) y: (180)
forever
change y by (-5)
if <touching [Cat v] ?> then
change [score v] by (1)
go to x: (pick random (-200) to (200)) y: (180)
end
end
Step 1 — Show the watcher
Open the Variables palette. Tick the box next to score. A watcher appears on the Stage. Now hit the flag and watch the watcher. It says 0 — and stays at 0, even when the cat clearly overlaps the kuih.
Step 2 — Slow the loop down
Drop a wait (0.2) seconds at the bottom of the forever loop. Now you can see each fall step. The kuih drops in stutters. Look closely at the moment the cat and kuih overlap.
Step 3 — Add a print-debug
Drop a say ((score)) for (1) seconds right after the change-score block. If the if-then fires, the kuih will hold up a speech bubble with the new score. Hit the flag.
Step 4 — Watch what happens
The kuih falls, the cat catches it … no speech bubble. The change-score line is not running, which means the if-then is reporting false. But the cat is clearly touching the kuih on the Stage. So the question must be wrong.
Step 5 — Inspect the dropdown
Click on the dropdown inside touching [Cat v]?. Daniel selected Cat, but his cat sprite is actually named Sprite1 — he never renamed it. The dropdown shows the sprite's real name. Daniel's "Cat" choice is probably from a different project.
Step 6 — Fix the dropdown
Change touching [Cat v]? to touching [Sprite1 v]? (or rename the sprite to Cat in the Sprite Pane — either works).
Step 7 — Test the fix
Hit the flag. Watch the score watcher. The cat catches the kuih — score goes to 1. Speech bubble pops up saying "1". Catch again — 2. The bug is fixed.
Step 8 — Remove the debug scaffolding
Now that it works, delete the say ((score)) for (1) seconds and the wait (0.2) seconds. Untick the watcher if you don't want it visible during play. The "shipping" version of the script is back to its original size — but it works.
The full assembled (fixed) stack
when flag clicked
set [score v] to (0)
go to x: (0) y: (180)
forever
change y by (-5)
if <touching [Sprite1 v] ?> then
change [score v] by (1)
go to x: (pick random (-200) to (200)) y: (180)
end
end
What you just did: turned a "the game doesn't work" complaint into a precise "the dropdown points at the wrong sprite" diagnosis — using three tools (watcher, slow-down, print-debug). That's the loop you'll use on every bug for the rest of Level 2.
Try It Yourself — three debugging drills 15 min
Goal: Build the stack below on the cat. Hit the flag. The cat moves but doesn't speak. Add a say ((x position)) for (1) seconds inside the loop to see what's going on with the x-coordinate.
when flag clicked
forever
change x by (5)
if <(x position) = (240)> then
say [At the edge!] for (1) seconds
end
end
Think: Your print-debug will reveal that x-position jumps in steps of 5 — so it goes 235, 240, 245 if you're lucky, or 233, 238, 243 if you're not. The () = () check almost never lands on exactly 240. Fix: use () > () instead. Same lesson as Aisyah's warmup, different bug.
Goal: Build a stack where a broadcast doesn't fire because of a typo. Sender (cat) broadcasts start-game. Receiver (a kuih sprite) listens for start_game. Run it — nothing happens. Use single-stepping (click the sender stack, then click the receiver stack separately) to confirm where the chain breaks.
when flag clicked
say [Get ready!] for (1) seconds
broadcast [start-game v]
when I receive [start_game v]
go to x: (0) y: (180)
show
Think: Click the sender stack by itself — the cat says "Get ready!" and you'd expect the kuih to react. It doesn't. Now click the receiver stack manually — the kuih jumps to position and shows. So both scripts work; the broadcast name just doesn't match. Fix: open the broadcast dropdown and pick the same name on both sides.
Goal: Below is Priya's "countdown timer" — it should count down from 10 to 0, then say "Time's up!". Instead it says "Time's up!" immediately and never counts. Use a watcher and a slow-down wait to find at least two bugs.
when flag clicked
set [time v] to (10)
forever
if <(time) = (0)> then
say [Time's up!] for (2) seconds
stop [all v]
end
change [time v] by (1)
end
Think: Two bugs. (1) Priya wrote change [time v] by (1) — it should be -1 (counting down). The watcher reveals time climbing instead of falling. (2) Without the slow-down, you'd never notice — the loop runs hundreds of times a second so "10" flashes past too fast to see. Drop a wait (0.5) seconds at the bottom and watch the value tick. The print-debug confirms each value as it passes.
Mini-Challenge — debug Aljay's lives counter 5 min
"Aljay's three-lives bug"
Aljay made a tiny "avoid the durian" game. The cat has 3 lives. Touching a durian costs 1 life. At 0 lives, the game should say "Game over!" and stop everything. Instead, the cat dies on the first touch and the game freezes without a message.
when flag clicked
set [lives v] to (3)
forever
if <touching [Durian v] ?> then
change [lives v] by (-1)
end
if <(lives) = (0)> then
say [Game over!] for (2) seconds
stop [all v]
end
end
Pick up two debugging tools before reading on. Which two would you try first? And what would they show you?
Reveal one valid solution
The fastest tools here are the lives watcher and a slow-down wait. Tick the lives variable to put it on the Stage. Add wait (0.2) seconds at the bottom of the forever.
Hit the flag and watch. The instant the cat touches the durian, the watcher plummets: 3 → 2 → 1 → 0 — in a single frame. The if-then for the durian touch is firing many times per second while the cat overlaps the durian. By the time the next loop checks lives = 0, lives has already gone negative (−1, −2, ...) — so the equality check is false and "Game over!" never appears.
Two fixes that both work:
- Change (lives) = (0) to (lives) < (1). Now the message fires for 0, −1, −2 too.
- Add a wait until <not <touching [Durian v] ?>> after the change-lives, so a single touch only costs one life.
Both fixes were found the same way: watch the variable. Without the watcher, Aljay would have re-stared at the stack for an hour. Don't read code to find a bug. Run it and watch.
Recap 3 min
You picked up three debugging moves that work on every Scratch project from here on. Single-stepping lets you click one block at a time to see exactly what it does. A temporary say ((variable)) turns the cat into a print statement so you can peek at any number mid-script. A wait (1) seconds inside a forever loop slows the action to human speed. Add the live variable watcher in the corner of the Stage and you've got four windows into a buggy script. The four most common bug families — broadcast typos, wrong dropdown picks, missing foreverloops, off-by-one repeats — all reveal themselves under those windows.
- Bug
- Any difference between what your stack does and what you wanted it to do. Bugs are normal — every script you'll ever build has them at some point.
- Single-stepping
- Clicking a single block in the Script Area to run just that block, or clicking each block in turn to walk a stack by hand.
- Print-debug
- A temporary say ((variable)) dropped into a stack so the sprite shows you a value at that point. Deleted once the bug is found.
- Watcher
- The little box on the Stage that shows a variable's live value. Toggle it on with the checkbox in the Variables palette.
- Off-by-one
- A bug where a loop runs one too many or one too few times. repeat (10) runs the body 10 times — not 11, not 9.
Homework 2 min
The Broken-Project Repair. Open one of your own past projects — ideally one that you remember had a small bug you never quite fixed. (If you can't think of one, open L02-43 catch-the-kuih or any of your homework files.) Apply the three debugging moves from today.
- Tick at least one variable watcher and play the project for 30 seconds. Note what value surprised you (if any).
- Drop a print-debug (say ((variable)) for (1) seconds) inside the busiest loop. Play again. Did the values match what you expected?
- If there's a forever loop you've never really watched, add a wait (0.5) seconds at the bottom and play once more. Anything jump out at you?
- Find and fix one bug. (Tiny bugs count — a typo, a wrong dropdown, a missing reset.) Remove your debug scaffolding (say + wait + watcher) before saving.
Save the repaired version as HW-L2-46-Debugged-<your-project-name>.sb3.
Bring back next class:
- The repaired
.sb3file. - One sentence describing the bug you found, and one sentence describing which debugging tool revealed it.
- One screenshot of your project with the debug scaffolding still in place, before you removed it. (Photo of the screen is fine.)
Heads up for next class: SCR-L02-47 moves your project from a lonely .sb3 on your hard drive to scratch.mit.edu — where teachers, friends, and the whole Scratch community can play and remix it. Bring a parent/guardian's email if you don't have a Scratch account yet.