Skip to main content

Stage 3: Make the Player Fish Grow

Course progressStage 3 of 10
~90 min
Your workspace

Keep your Scratch project tab open all week. Open in a new tab so you don’t leave the course.

Build

two variables and a size loop that watches them

Learn

how a variable remembers a number across the whole game

Ship

a tiny fish that's ready to grow as it eats

Teacher demo

Show the room. This stage introduces variables — the new concept of the week. Move slowly:

  1. Click the Player sprite, then Variables (orange) in the block palette. Click Make a Variable. Name it playerAlive. Choose For all sprites.
  2. Click Make a Variable again. Name it playerSize. For all sprites.
  3. Drag in the existing when green flag clicked script from Stage 2. Add new blocks between the existing setup blocks and the forever loop:
    • set playerAlive to 1
    • hide variable playerSize
    • set playerSize to 15
  4. Drag a separate forever loop somewhere else (not the keyboard one). Inside it:
    • set size to (playerSize) %
    • if (playerSize > 100) then broadcast (playerWon) — type "playerWon" as a new message
    • wait until (playerSize > size)
  5. Click green flag. Show the tiny fish. Manually edit playerSize to 50 in the variable. Show the fish grow.

That growth moment is the wow.

The big idea

Today the Player Fish learns to remember things.

So far, every block we've written has been instructions — "go here," "switch costume," "change y by 2." Today we add variables. A variable is a name we give to a number that the whole game can read and change.

For Fish Food, we need two variables:

  • playerAlive1 while the player is still in the game, 0 when the game ends. Think of it as the game's on switch.
  • playerSize — the fish's current size, as a percentage. Starts at 15 (a tiny fish). When the fish eats a smaller enemy, this number goes up. When it reaches 100, the player wins.

Variables are powerful because they live outside any one sprite. The Player sets playerSize to 15 today. The Enemy Fish (Stage 8) will change playerSize when the player eats it. The game's stats screen (Stage 10) will read playerSize at the end. Three different sprites, all sharing one number through a name.

The new game-design move today is size as state. The fish grows visibly when it eats. The player can SEE that they're winning. That's much more satisfying than a hidden score.

New words
variable
a name we give to a number the game remembers
initialize
set a variable to its starting value at the start of the game
size
how big the sprite is — measured as a percentage of its full size
broadcast
send a message that other code can listen for
hide variable
keep a variable in the game but invisible on the stage
Before you start

Stages 1 and 2 should be done — your Player Fish has costumes, sounds, a name, and a keyboard-driven forever loop.

Build it

Step 1 — Make the playerAlive variable

In the block palette, click Variables (orange).

Click Make a Variable. A pop-up appears.

  • Name: playerAlive
  • Select For all sprites (we want the enemy fish to be able to read this later)
  • Click OK

A new section appears in the Variables category with playerAlive and some blocks for using it. By default it's visible on the stage — leave it visible for now.

Step 2 — Make the playerSize variable and hide it

Same process:

  • Click Make a Variable.
  • Name: playerSize
  • Select For all sprites.
  • Click OK.

Two variables now exist. But for playerSize, we don't want the player to see the number — it would clutter the stage. We'll hide it.

Drag the hide variable (playerSize) block into the already-existing setup section of your Stage 2 script. Put it after the show block and before the forever loop.

Step 3 — Initialize both variables at game start

The fish needs to know where it stands at the beginning of every round. We initialize both variables — set them to their starting values.

In your Stage 2 script (the when green flag clicked chain), add these blocks between the show block and the forever loop:

Add these setup blocks

set [playerAlive v] to (1)
hide variable [playerSize v]
set [playerSize v] to (15)

playerAlive starts at 1 (alive). playerSize starts at 15 (a tiny fish, only 15% of full size).

Step 4 — Add a separate forever loop for size

The size logic is its OWN script. It runs alongside your Stage 2 keyboard loop. Both scripts run at the same time when you click the green flag.

Drag a fresh when green flag clicked block into the code area (separate from your Stage 2 script). Snap a forever loop below it.

Inside the new forever, add set size to (playerSize) %. (Drag the round playerSize variable from the palette into the slot.)

Click the green flag. The fish should appear tiny — only 15% of its normal size. That's because playerSize is 15.

Step 5 — Check for the win condition

The player wins when their fish reaches 100%. We add an if-block that broadcasts a playerWon message when that happens.

Inside the same forever loop you just made, add an if/then block after set size to (playerSize) %.

Drag > (greater than) from Operators into the if's diamond slot. Put playerSize on the left side and 100 on the right.

Inside the if, drag broadcast (message1). Click the dropdown, choose New message, and type playerWon. Click OK.

Your check should look like:

if (playerSize > 100) then
broadcast (playerWon)

Step 6 — Wait until the size catches up

There's a tiny technical move that makes the loop run smoothly. When playerSize jumps up (because the fish ate an enemy), the actual rendered size of the sprite takes a moment to catch up. To keep the loop from spinning wildly, we add a wait until at the end of the forever.

Drag wait until (<condition>) from Control. Inside the diamond, build playerSize > size (drag playerSize from Variables, drag size from Looks, use the > operator).

The full size loop now reads:

Player size loop

when green flag clicked
forever
set size to (playerSize) %
if <(playerSize) > (100)> then
broadcast [playerWon v]
end
wait until <(playerSize) > (size)>
end

Click the green flag. The fish should appear tiny. It won't grow on its own yet — that's Stage 8, when the enemy fish make playerSize go up.

Save your project.

Understand it

The most important idea today is that the variable is the bridge between sprites. Stage 2's keyboard script doesn't need to know what playerSize is. Stage 8's enemy script will change playerSize but doesn't need to know anything about the Player sprite directly. Both scripts talk to each other through a name — and that name's value lives in the variable.

The reason we initialize at the top of the script is restart safety. After the player loses a round (Stage 4), playerAlive is set to 0. If we didn't reset it back to 1 when the green flag is clicked again, the next round would start with the game already over. Initialization makes every round start fresh.

The reason we hide playerSize but leave playerAlive visible (for now) is a design choice. playerSize is a number from 15 to 100 — meaningless to most players. playerAlive is 1 or 0 — easy to read while we're testing. By Stage 10, we'll hide them both because the player doesn't need to see them.

The reason we use > (greater than) 100 instead of = 100 is defensive code. If the fish eats a large enemy and playerSize jumps from 95 to 103, an = 100 check would miss the win condition. > 100 catches every case where the size has crossed the line.

The wait until (playerSize > size) trick is subtle. The size block in Scratch reads the rendered size. When playerSize updates, the rendered size needs a moment to catch up. Without the wait, the loop would fire over and over before the visual change registered. Trust this block — you don't have to understand exactly how Scratch's renderer works.

Try this

Learning beat

Try this

Three short experiments. Predict before you run, then test your guess.

Predict first

Change set playerSize to 15 to set playerSize to 50. Predict — will the game be easier or harder to win? Try it. Why does the starting size matter so much?

Compare

On the stage, double-click the playerSize variable readout (if it's visible) — or right-click it to show it. Watch the number while you click the green flag. Now manually set it to 75 by clicking the variable on the stage and typing. The fish grows live. What does this tell you about variables?

Connect

Stage 4 handles winning and losing. The win path runs when playerSize > 100 triggers the playerWon broadcast you just wrote. The lose path runs when... something else broadcasts playerEaten. Which sprite will send the playerEaten message?

Test your stage

  • You have two variables: playerAlive and playerSize.
  • Both variables are For all sprites.
  • playerAlive starts at 1 when the green flag is clicked.
  • playerSize starts at 15 when the green flag is clicked.
  • The fish appears tiny on the stage at game start (15% of full size).
  • If you manually set playerSize to a number bigger than 100 on the stage, the fish broadcasts playerWon (nothing happens visibly yet, but the message goes out).
  • Your project is saved.
  • Design check. Look at the playerSize variable on the stage. Hide it (right-click → hide). Is the game still readable without seeing the number? It should be — players see the fish size, not the number.

If it breaks

  • The fish is normal size, not tiny. Two suspects. First, set playerSize to 15 may not be in your script — check the setup section. Second, the size forever loop may not exist, or set size to (playerSize) % may not be inside it.
  • The fish doesn't change size when I edit the variable on the stage. The size forever loop is missing or stopped. Make sure you have two when green flag clicked scripts: one for keyboard (Stage 2), one for size (this stage).
  • Scratch says "playerSize is undefined." You probably didn't make the variable, or you spelled it differently — like playersize (lowercase) or playerSize1. Variable names must match exactly. Rename or remake.
  • My playerSize variable doesn't show in the dropdowns. Click Variables in the palette and confirm it's there. If not, click Make a Variable and re-create it as For all sprites.
  • The broadcast playerWon dropdown doesn't have my message. When you create the broadcast block, click the dropdown and choose New message to type "playerWon." Don't type it in another place — Scratch wants it created via the dropdown.
Coach notes

This is the hardest stage on the Player side. Variables are a new concept for most kids 7–9, and Scratch's variable UI (Make a Variable → For all sprites vs This sprite only → checkboxes for show/hide) is more friction than the building-block stuff they've done so far.

The single most common failure: making playerSize as For this sprite only. The enemy fish (Stage 8) won't be able to change it from another sprite. Walk the room after Step 2 and confirm both variables are For all sprites.

The second most common: forgetting to make a SEPARATE forever loop for size. Some kids try to put the size logic inside their Stage 2 keyboard loop, which works but is harder to debug. The book uses two separate when green flag clicked scripts, and we follow it. Two scripts = two heartbeats = cleaner separation of concerns.

The "wait until (playerSize > size)" block is genuinely advanced. Most 7–9 year olds will not understand why it's needed. Don't dwell on it — just say "this block makes the loop wait until Scratch finishes drawing" and move on. They'll see the consequence in Stage 8 when the eating animation feels smooth instead of jittery.

For Step 5's broadcast, the New message dropdown is non-obvious — many kids will try to type "playerWon" directly in the broadcast block's text field, which doesn't work. Show the dropdown explicitly during the teacher demo.

If a camper finishes by minute 60, push them into the medium stretch (tune the difficulty). The hard stretch (smooth growth animation) is great preparation for Stage 8's "growing while eating" moment — but only if they're way ahead.