Stage 4: Win or Lose
Keep your Scratch project tab open all week. Open in a new tab so you don’t leave the course.
two broadcast handlers — one for winning, one for losing
how one sprite shouts a message and another listens
a game that can be both won and lost
Show the room — the win and lose paths are mirror patterns. Build both side by side so the kids SEE the parallel:
- Click the Player sprite, Code tab.
- Drag in two when I receive event blocks. Set one to playerEaten (lose), the other to playerWon (win).
- Build the lose chain: set playerAlive to 0, set rotation style all around, point in direction -90, stop other scripts in sprite, start sound Bubbles, repeat 100 change pixelate effect by 1, broadcast gameover, hide.
- Build the win chain right next to it: set playerAlive to 0, switch costume to Party Hat-a, stop other scripts in sprite, stop all sounds, start sound Eggs, wait 5 seconds, repeat 100 change ghost effect by 1, broadcast gameover, hide.
- Test by typing
broadcast playerEatenin the broadcast dropdown manually, thenplayerWon. Watch both endings play.
Then say "Look at both chains. They're almost the same — the difference is the FEEL."
The big idea
Until today, the fish could swim — but it couldn't win or lose. Today we add the two endings.
The whole concept comes down to a Scratch superpower called broadcasting.
one sprite another sprite
shouts a message listens for it
│ │
▼ ▼
broadcast (playerWon) when I receive (playerWon)
do all this stuff →
The Player Fish doesn't check itself to see if it's won. That would be slow and weird. Instead, the size-check script from Stage 3 shouts the message playerWon when playerSize > 100. A separate listener script — the one we build today — catches the message and runs the celebration code.
We build two listeners today:
- When I receive playerEaten — the lose path. Set the player to dead, rotate the fish, play a sad sound, dissolve into pixels.
- When I receive playerWon — the win path. Set the player to dead too (game's over either way), switch to the party-hat costume, play a celebration sound, fade out gently.
Both endings do the same overall job (end the round and start the cleanup). The details are what tell the story: pixelate + bubbles + a rotated fish feels like getting eaten. Party hat + eggs + ghost fade feels like winning. Same shape of code, opposite feel.
- when I receive
- an event block that runs when its message is broadcast
- broadcast
- send a message to every sprite listening
- stop other scripts in sprite
- kill the other forever loops on this same sprite
- effect
- a visual change — pixelate makes the sprite blocky, ghost makes it see-through
- all around
- a rotation style that lets the sprite rotate freely instead of only flipping left and right
Stage 3 should be done — your Player sprite has playerAlive and playerSize variables, and your size loop broadcasts playerWon when playerSize > 100.
Build it
Step 1 — Build the LOSE listener
We start with the loss path. (The lose broadcast playerEaten will be sent by the enemy fish in Stage 8 — we're building the listener now so it's ready.)
In the Player's code area, drag in a fresh when I receive (message1) block from Events (yellow). Click its dropdown, choose New message, type playerEaten, click OK.
Snap these blocks below it, in order:
Lose listener
A few notes on each block:
- set playerAlive to 0 — tells the rest of the game "the player is dead now."
- set rotation style (all around) — lets the fish rotate freely. The default left-right would only flip it horizontally.
- point in direction (-90) — rotates the fish for the losing animation, matching the book's block stack.
- stop other scripts in sprite — this kills the Stage 2 keyboard loop and the Stage 3 size loop. They can't keep running while the game is ending.
- start sound (Bubbles) — sad watery sound.
- repeat 100 + change pixelate effect by 1 — the fish slowly pixelates into a blocky mess over 100 frames.
- broadcast (gameover) — sends the game-is-truly-over message to the stats screen (Stage 10).
- hide — the fish disappears completely.
Note: type gameover lowercase, no space. We'll use the exact same message in the win path.
Step 2 — Build the WIN listener
Now drag a second when I receive block, set its message to playerWon (the broadcast you already made in Stage 3 should be in the dropdown).
Snap the win chain below it:
Win listener
Notes:
- set playerAlive to 0 — game's over, win or lose. Same line as the lose path.
- switch costume to (Party Hat-a) — the fish puts on a party hat. The visual reward for winning.
- stop other scripts in sprite — same reason as lose.
- stop all sounds — the music (Stage 9) is probably playing. We silence it for the celebration moment.
- start sound (Eggs) — a bright celebration sound. (Yes, Scratch's "Eggs" sound — it's a wobbly happy noise that fits.)
- wait 5 seconds — give the player time to enjoy the win before the fish fades.
- repeat 100 + change ghost effect by 1 — the fish slowly fades out over 100 frames. Ghost is Scratch's transparency effect.
- broadcast (gameover) — same end signal as the lose path.
- hide — the fish disappears.
Step 3 — Test both endings
We can't fully test the lose path yet (Stage 8 will trigger it). But we can fake both manually.
Click the green flag. The fish appears tiny on the stage.
Test the WIN path:
- On the stage, find the
playerSizevariable. Show it if it's hidden (right-click → show variable). Click on the number and type101. The size loop fires, broadcastsplayerWon, and your win chain runs. The fish should put on a party hat, the Eggs sound plays, and after 5 seconds the fish fades out.
Test the LOSE path:
- Click the green flag to reset.
- Open the broadcast dropdown trick: drag a fresh broadcast (playerEaten) block into a blank spot. Click it. The lose chain fires — sad sound, rotated fish, pixelate fade.
- Delete the test broadcast block when you're done.
Save your project.
Understand it
The most important pattern in this stage is the mirror. Read both listeners side by side. Almost every line has a counterpart in the other chain:
| Lose chain | Win chain |
|---|---|
| set playerAlive to 0 | set playerAlive to 0 |
| set rotation style (all around) | switch costume to (Party Hat-a) |
| point in direction (-90) | (no equivalent — fish stays upright) |
| stop other scripts in sprite | stop other scripts in sprite |
| (no equivalent) | stop all sounds |
| start sound (Bubbles) | start sound (Eggs) |
| repeat 100 change pixelate | wait 5 seconds, then repeat 100 change ghost |
| broadcast (gameover) | broadcast (gameover) |
| hide | hide |
Pros call this parallel structure. When two pieces of code do similar jobs, you write them so the shape matches. Future-you (or another developer) can read both side by side and instantly spot the differences. The differences are where the story lives.
The reason both endings set playerAlive to 0 is that the rest of the game (especially Stage 9's timer and Stage 10's stats screen) checks playerAlive to decide if the round is still going. Setting it to 0 stops the timer, freezes the score, and signals everything else to wind down. Win or lose, the game is over.
The reason we stop other scripts in sprite is critical. Without that block, the Stage 2 keyboard loop would keep running — the player could still move their pixelated dying fish. The Stage 3 size loop would keep running — playerSize could change after the death sequence started. Stop other scripts in sprite kills both, leaving only the win/lose chain running. Clean shutdown.
The different visual effects (pixelate vs ghost) tell the player two different stories. Pixelate makes the fish look like it's breaking apart — your fish lost its battle. Ghost makes the fish fade out gently — your fish is celebrating in peace. Same Scratch effect category, opposite emotional read.
The gameover broadcast at the end of both tells the rest of the game "we're truly done now, show the stats screen." Stage 10 listens for this message. By using the same lowercase string in both chains, we make sure the stats screen runs either way.
Try this
Try this
Three short experiments. Predict before you run, then test your guess.
Comment out (remove) the stop other scripts in sprite block in the LOSE chain. Trigger the lose path. Predict what happens. Try it. What broke? Put the block back when you're done.
Swap the effects: use ghost in the LOSE chain and pixelate in the WIN chain. Trigger both. Which version feels right? Why do effects match an emotion better when you pick them carefully?
Stage 5 starts building the enemy fish. The enemy is the one who will eventually broadcast playerEaten when it bumps into the player. Look at your listener for playerEaten. What does the enemy NEED TO KNOW before it can send that broadcast?
Test your stage
- You have a when I receive (playerEaten) script with the full lose chain.
- You have a when I receive (playerWon) script with the full win chain.
- Setting
playerSizeto101on the stage triggers the WIN path (party hat, eggs, fade out). - Manually broadcasting
playerEatentriggers the LOSE path (rotated fish, bubbles, pixelate). - Both chains end with broadcast (gameover) and hide.
- Your project is saved.
- Design check. Compare your two chains side by side in the code area. Are they parallel? Is the difference visible in 3 seconds of looking?
If it breaks
- The win chain runs but the fish stays as Fish-a. The switch costume to (Party Hat-a) block is missing or set to the wrong costume. Drop down and pick Party Hat-a explicitly.
- The lose chain runs but the fish doesn't rotate. Two suspects. First, did you add set rotation style (all around)? Without it, the fish stays in left-right mode. Second, did you set point in direction to
-90as shown in the book stack? - The Bubbles sound never plays. Two possibilities. First, did you add the sound to the Player sprite in Stage 1? Second, is the sound named exactly Bubbles in the Sounds tab? Sound names are case-sensitive.
- The fish pixelates but never comes back. That's the point — the fish is supposed to stay broken until the next round. Click the green flag again. The setup section resets everything: switch costume to Fish-a, set rotation back to left-right, clear effects (you may need to add
clear graphic effectsto the start of the script — Stage 9 adds it explicitly). - The
gameoverbroadcast doesn't seem to do anything. That's correct for today. Stage 10 will receive it. Right now nothing is listening yet. - Both chains broadcast
gameoverbut only one fires. Make sure you spelled the receiving message in each one —playerEatenfor lose,playerWonfor win. If bothwhen I receiveblocks say the same message, only one ending exists.
This stage introduces broadcast/receive, which is the most powerful (and most confusing) Scratch pattern for kids 7–9. Move slowly. The book has both endings on separate pages; we put them on one page for pedagogy reasons (mirror pattern visible).
The single most common failure: building only ONE of the two listeners. Walk the room after Step 2 and confirm every laptop has BOTH when I receive (playerEaten) and when I receive (playerWon) scripts.
The second most common: typo in the broadcast names. playerEaten (one word, lowercase 'e', not "playereaten" or "Player Eaten"). playerWon (one word, lowercase 'w' not "PlayerWon"). gameover (one word, lowercase). Walk the room and read names out loud.
The "stop other scripts in sprite" block is critical and easy to miss. If a camper's fish keeps moving after death, that's the issue.
For the manual testing in Step 3 — kids will think "I can't test without Stage 8 done." Show them the trick: manually edit playerSize to 101 on the stage to trigger win. Manually broadcast playerEaten from a dragged-in block to trigger lose. This is real engineering — testing one piece without the others.
If a camper finishes early, push them into the medium stretch (tuning the celebration). The hard stretch (say blocks for context) is great prep for the stats screen — only push if they're way ahead.