Learning Goals 3 min
By the end of this lesson you will be able to:
- Implement gravity in Scratch using a single velocity-y variable that gets more negative by 1 every frame, then is added to the sprite's y.
- Reset velocity-y to
0when the player touches a platform colour — so the sprite stops falling instead of sinking through. - Tune the feel of gravity by changing one number: change [velocity-y v] by (-1) is normal gravity; change [velocity-y v] by (-2) feels heavy; change [velocity-y v] by (-0.5) feels like the moon.
Warm-Up — drop a coconut 7 min
Watch a coconut fall from a palm tree. The first instant after it lets go, it barely moves. A second later, it's hurtling. By the time it hits the ground, it's fast. It didn't fall at a constant speed — it sped up the whole way down.
Compare this constant-speed Scratch fall:
when flag clicked
go to x: (0) y: (150)
forever
change y by (-3)
end
Try it mentally. The sprite drops smoothly and evenly from the top to the bottom of the Stage. Does that look like a falling coconut, or like a smooth elevator going down?
Reveal the answer
It looks like a smooth elevator. Real gravity doesn't move things at a constant speed — it constantly adds speed. After half a second, the coconut is moving twice as fast as it was. After a second, three times as fast. The fall accelerates.
To get that feel in Scratch, we can't use change y by (-3). The −3 is the same every frame, so the speed is the same every frame. We need the falling speed to grow every frame. That means storing the speed in a variable and changing the variable, not the y directly.
That variable is velocity-y. Today you'll meet it, and your sprites will finally fall like real things instead of like elevators.
New Concept — velocity-y and acceleration 15 min
Gravity in Scratch is two numbers and one trick.
velocity-y — how fast you're falling right now
Make a new variable, velocity-y, "for this sprite only" on the player. It starts at 0. This variable holds the sprite's current vertical speed. Positive means going up. Negative means going down. Zero means standing still.
Every frame: two changes
Every frame, inside forever, do two things in order:
- change [velocity-y v] by (-1) — gravity pulls the speed downward.
- change y by (velocity-y) — apply that speed to the sprite's actual position.
when flag clicked
go to x: (0) y: (150)
set [velocity-y v] to (0)
forever
change [velocity-y v] by (-1)
change y by (velocity-y)
end
Trace the maths
Walk through what happens after the flag, frame by frame:
- Frame 0: y = 150, velocity-y = 0. Change by −1 → velocity-y = −1. Move y by −1 → y = 149.
- Frame 1: velocity-y = −1. Change by −1 → velocity-y = −2. Move y by −2 → y = 147.
- Frame 2: velocity-y = −2. Change by −1 → velocity-y = −3. Move y by −3 → y = 144.
- Frame 3: velocity-y = −3. Change by −1 → velocity-y = −4. Move y by −4 → y = 140.
- …
- Frame 10: velocity-y ≈ −11. Move y by −11. The sprite is hurtling.
The drops per frame go 1, 2, 3, 4, 5, 6, 7, 8… That's acceleration. That's the coconut. That's real gravity.
Landing — stop falling when you touch a platform
Without landing, the sprite falls forever — straight off the bottom of the Stage. To land, check whether the sprite is touching the platform colour, and if so, reset velocity-y to 0. With velocity-y at 0, the change y by (velocity-y) does nothing — the sprite stops falling.
when flag clicked
go to x: (0) y: (150)
set [velocity-y v] to (0)
forever
change [velocity-y v] by (-1)
change y by (velocity-y)
if <touching color [#964b00] ?> then
set [velocity-y v] to (0)
change y by (1)
end
end
#964b00 is the platform colour. The change y by (1) at the bottom nudges the sprite up by one pixel — just enough to get it out of the platform so it isn't "touching" next frame.Tuning gravity
The −1 in change [velocity-y v] by (-1) is the strength of gravity. Make it more negative for a heavier feel:
- change [velocity-y v] by (-0.5) — moon gravity. The sprite drifts down slowly.
- change [velocity-y v] by (-1) — normal. Earth-like.
- change [velocity-y v] by (-2) — heavy. Like falling through syrup. Or like an anvil.
- change [velocity-y v] by (-4) — slamming. Use for crash-down moves.
One number, the entire physics of your game changes. Mario uses around −1. Sonic uses around −0.7. Crash Bandicoot uses around −1.5.
Worked Example — drop the cat onto a platform 12 min
Open Scratch. Eight steps. We'll build the simplest possible "cat falls onto a floor" demo.
Step 1 — Make the velocity-y variable
Click the cat. Variables panel → Make a Variable → name it velocity-y. Tick "for this sprite only". Tick the show-on-Stage box so you can watch the number change.
Step 2 — Paint a platform sprite
Click the Paint icon to make a new sprite. Use the rectangle tool with brown fill (#964b00). Draw a long, flat rectangle — wider than tall. Name the sprite Floor. Drag it on the Stage to about y: −120.
Step 3 — Position the cat high up
Click the cat. Drag it to x: 0, y: 150 — near the top of the Stage.
Step 4 — Drop in the hat and initial values
when flag clicked
go to x: (0) y: (150)
set [velocity-y v] to (0)
Sets the cat back to the top every time you click the flag, and resets the falling speed.
Step 5 — The forever loop
Drag forever under the setup blocks. The next three steps go inside this C.
Step 6 — Gravity (acceleration)
Drag change [velocity-y v] by (-1) inside the forever. This is the gravity strength. Keep it at −1 for now.
Step 7 — Apply the velocity
Drag change y by () below the gravity block. In the empty round slot, drop the round (velocity-y) reporter.
Step 8 — The landing check
Drag if <> then below the change-y. In the diamond: touching color [#964b00]? (click the colour swatch, then click the brown floor on Stage to pick the exact colour). Inside the if: set [velocity-y v] to (0) and change y by (1).
Click the flag
The cat appears at the top. It barely moves for the first half-second. Then it falls faster. Then faster. Then it thunks onto the brown floor and stops dead. Watch velocity-y on the Stage: it ticks down to about −16 by the time the cat lands.
The full assembled stack
when flag clicked
go to x: (0) y: (150)
set [velocity-y v] to (0)
forever
change [velocity-y v] by (-1)
change y by (velocity-y)
if <touching color [#964b00] ?> then
set [velocity-y v] to (0)
change y by (1)
end
end
What you just built: the physics engine for every platformer ever made. Two numbers, three lines of code, and your sprite obeys gravity. Add a jump (next lesson) and you've got Mario.
Try It Yourself — three gravity drills 15 min
Goal: Change the gravity strength to −0.5. The cat should fall in slow-motion, like an astronaut on the moon. Watch the velocity-y variable on the Stage to see it climb more slowly.
when flag clicked
go to x: (0) y: (150)
set [velocity-y v] to (0)
forever
change [velocity-y v] by (-0.5)
change y by (velocity-y)
if <touching color [#964b00] ?> then
set [velocity-y v] to (0)
change y by (1)
end
end
Think: Half the gravity, half the acceleration. The cat takes about twice as long to reach the floor. One number is the entire difference between Mario and a moon-walker.
Goal: Add a second platform higher up — say, at y: 0. Paint another brown rectangle, name it Ledge. Drag it to x: 100, y: 0. Reposition the cat to start at x: 100. The cat should now land on the ledge, not the floor.
when flag clicked
go to x: (100) y: (150)
set [velocity-y v] to (0)
forever
change [velocity-y v] by (-1)
change y by (velocity-y)
if <touching color [#964b00] ?> then
set [velocity-y v] to (0)
change y by (1)
end
end
Think: The cat doesn't know about ledges vs floors. It just knows about the brown colour. Every platform that's brown counts. If you wanted some platforms to be solid and others to be "pass-through", you'd give them different colours and only check for the solid colour.
Goal: Cap the falling speed. Without a cap, velocity-y can reach −50 or worse on long falls, and the cat teleports through thin platforms. Stop velocity-y from going below −12.
when flag clicked
go to x: (0) y: (150)
set [velocity-y v] to (0)
forever
change [velocity-y v] by (-1)
if <(velocity-y) < (-12)> then
set [velocity-y v] to (-12)
end
change y by (velocity-y)
if <touching color [#964b00] ?> then
set [velocity-y v] to (0)
change y by (1)
end
end
Think: This is called a terminal velocity. Real falling things hit a top speed too — air resistance fights gravity until they cancel out. In Scratch you fake it with an if-then. Every serious platformer has one.
Mini-Challenge — Arjun's sinking cat 5 min
"My cat falls through the floor and keeps going"
Arjun wrote the gravity stack but his cat sinks straight through the brown floor and disappears off the bottom. Here's his code:
when flag clicked
go to x: (0) y: (150)
set [velocity-y v] to (0)
forever
change [velocity-y v] by (-1)
change y by (velocity-y)
if <touching color [#964b00] ?> then
change y by (1)
end
end
What's missing inside the if, and why does the cat keep falling without it?
Reveal one valid solution
Arjun pushes the cat up by 1 pixel when it touches the floor — but he never resets velocity-y to 0. So the next frame, velocity-y is still −16 (or whatever big negative number it had reached). Gravity adds another −1 → −17. Then change y by (velocity-y) moves the cat down by 17 pixels — instantly back through the floor, and below. The 1-pixel push-up can't possibly keep up with a 17-pixel-per-frame drop.
The fix: add set [velocity-y v] to (0) inside the if, before the push-up:
when flag clicked
go to x: (0) y: (150)
set [velocity-y v] to (0)
forever
change [velocity-y v] by (-1)
change y by (velocity-y)
if <touching color [#964b00] ?> then
set [velocity-y v] to (0)
change y by (1)
end
end
Now the speed is zeroed at the moment of impact. The next frame, gravity makes it −1, the cat tries to fall by 1, immediately touches again, resets to 0 again. The cat sits on the floor with velocity-y bouncing between 0 and −1 every frame — invisibly stable. Resetting the velocity is what "landing" actually means.
Recap 3 min
You met the variable trick that powers every platform game in history. Instead of moving y by a fixed amount each frame, you store the falling speed in velocity-y and let gravity change that speed by −1 every frame. The fall accelerates. Add the speed to y, and the sprite falls like a real coconut, not like an elevator. When the sprite touches a platform, reset velocity-y to 0 and nudge up by 1 pixel — that's "landing".
- velocity-y
- A "for this sprite only" variable that holds the sprite's current vertical speed. Negative = falling. Positive = rising. Zero = not moving vertically.
- Acceleration
- A change in speed over time. Gravity in Scratch is "speed gets one more negative every frame" — that's constant acceleration downward.
- Landing
- The moment a falling sprite touches a platform. In code: reset velocity-y to 0 and push the sprite up by 1 pixel so it's no longer overlapping the platform.
- Terminal velocity
- The maximum falling speed a sprite is allowed to reach. Without a cap, long falls can make velocity-y huge and the sprite teleports through thin platforms.
- Gravity strength
- The number you subtract from velocity-y each frame. −1 is normal. −0.5 is moon. −2 is heavy. Tuning this one number changes the feel of your whole game.
Homework 2 min
Durian Drop. A durian falls from a tree onto the ground. Same physics as today, fresh skin.
- Paint a small spiky green durian sprite. Place at x: 0, y: 150.
- Paint a brown ground (
#964b00) at the bottom of the Stage — y around −150. - Give the durian a velocity-y variable, "for this sprite only", and tick it on the Stage.
- Write the gravity loop exactly like today's example. Drop it. The durian should accelerate and thunk onto the ground.
- Bonus 1: change the gravity strength to
−1.5. Does the durian feel heavier? - Bonus 2: add a play sound [thud v] inside the if-touching, so it makes a noise on impact.
Save as HW-L3-39-Durian-Drop.sb3.
Bring back next class:
- The
.sb3file. - Your answer to: "What gravity strength feels most like a real durian to you? Why? (Try −0.5, −1, −1.5, −2 and pick.)"
Heads up for next class: SCR-L03-40 adds jumping. The whole jump is one line: when the up-arrow is pressed and the sprite is on the ground, set [velocity-y v] to (15). Gravity does the rest — the sprite shoots up, slows, peaks, falls back down. Same variable, same loop, jumps for free.