What you will learn
- Use coordinates to position and constrain moving sprites.
- Combine keyboard input, loops, and conditions into responsive controls.
- Use velocity variables to change direction without changing speed.
- Track scores, reset a round, and stop the game at a winning condition.
In this project 0/8 steps
Before you start
You need basic mouse and keyboard skills. No coding experience needed.
A computer
RequiredAny computer that can run the Scratch 3 web editor. A Raspberry Pi works too, but you do not need one.
Keyboard + mouse
RequiredBoth players share one keyboard. Use a mouse or trackpad to drag blocks. Touch-only screens will not work.
Scratch 3 web editor
FreeRuns in your browser. You do not need an account to save your project to your computer.
Open editorStarter project
IncludedThe court, two paddles, the ball, and four variables, ready to go. You add all the code.
Get starter fileWHAT YOU'LL NEED
Raspberry Pi 5 Complete Starter Kit4GB, acrylic case$199.99Optional. Scratch runs in any web browser.Words to know
- Sprite
- A character or object on the stage. This game has three: two paddles and a ball.
- Script
- A stack of blocks snapped together. Each sprite runs its own scripts.
- Variable
- An orange block that remembers a value, like Left score or vx. The value can change while the game runs.
- Reporter
- A round or pointed block that holds a value or a true/false answer. It drops into a slot inside another block.
Set up the desktop, screen, keyboard, mouse, and internet first. This is a software project, so leave the GPIO pins empty. Raspberry Pi setup guide.
One court. Three sprites. Four variables.
The ball has a left-right speed, vx, and an up-down speed, vy. Paddles only move up and down. Hitting a wall flips vy. Hitting a paddle flips vx. A miss scores a point for the other player.
Sprite sizes and positions
| Sprite | Starting position | Costume size | Control |
|---|---|---|---|
| Left Paddle | x -210 / y 0 | 12 x 80 | W / S |
| Right Paddle | x 210 / y 0 | 12 x 80 | Up / Down arrows |
| Ball | x 0 / y 0 | 14 diameter | vx / vy |
From first block to first match
Open your project workspace
GoalStart with artwork that is already the right size. You will write all of the game code yourself.
Download the starter project (.sb3)- Download the starter file with the button above, then open the Scratch web editor at scratch.mit.edu/projects/editor.
- Choose File > Load from your computer and pick scratch-pong-starter.sb3. Loading replaces whatever was open, so save other work first.
- You should see three sprites: Left Paddle, Right Paddle, and Ball. Click each one. The Code area should be empty.
- Open the orange Variables category. Left score, Right score, vx, and vy should all be there. Only the two scores show on the stage.
- Name your project, for example My First Pong Game. Keep this guide and the editor side by side.
Three named sprites are visible, both scores read 0, and no sprite has any code yet.
Mine doesn't work
Code already there? You loaded the completed game, not the starter. Reload the starter file.
Open the Scratch editor, choose File > Load from your computer, and select the .sb3 file. Redownload it if necessary; do not unzip or rename its internal files.
Understand why
Everyone starts with the same sprites, so the numbers in later steps (like 140 and 196) fit your game exactly.
Give each player a paddle
GoalThe left player uses W and S. The right player uses the up and down arrows. Paddles only move up and down.
- Select Left Paddle and build the Left Paddle stack. Each block color tells you which category to open: yellow Events, blue Motion, gold Control, light-blue Sensing, green Operators.
- Select Right Paddle and build its stack. It starts at x 210 and uses the arrow keys.
- Everything below go to x goes inside forever. The yellow green-flag block stays on top.
- Click the green flag, click the stage, then try all four keys. Click the red stop sign when you are done.
when green flag clicked
go to x: -210 y: 0
forever
if <key [w] pressed?> then
change y by 8
end
if <key [s] pressed?> then
change y by -8
end
if ((y position) > 140) then
set y to 140
end
if ((y position) < -140) then
set y to -140
end
endwhen green flag clicked
go to x: 210 y: 0
forever
if <key [up arrow] pressed?> then
change y by 8
end
if <key [down arrow] pressed?> then
change y by -8
end
if ((y position) > 140) then
set y to 140
end
if ((y position) < -140) then
set y to -140
end
endPredict, then testWhat happens if you change both 8s to 4? Predict it, try it, then change them back.
W/S moves only the blue paddle and the arrows move only the pink one. Neither paddle can leave the top or bottom of the stage.
Mine doesn't work
A paddle moves once and stops? Its key checks are outside forever. Nothing moves? Click the stage first so it gets the key presses.
Click the stage, then try the controls again. Make sure a sprite-name or number field is not focused. Check each script is on the correct paddle.
Try a different keyboard or change one player's keys. Keep a record of the replacement controls so both players know what to use.
Understand why
The stage runs from y = -180 to 180. Each paddle is 80 tall, so its center must stay between -140 and 140 to keep the whole paddle on screen.
Make the ball move
GoalGive the ball two speeds: vx for left and right, vy for up and down. Then start the main game loop.
- Select Ball and build this stack. The setup blocks run once, before the loop.
- For the loop, use gold repeat until, not forever. Build its condition now: two green = blocks joined by a green or block, with the orange Left score and Right score reporters inside.
- Until someone reaches 5, repeat until keeps looping just like forever. You will not need to rebuild this loop later.
- The set vy block holds a green pick random reporter. The if block after it swaps 0 for 2, so the serve is never perfectly flat.
- Click the flag. The ball waits, then moves right and up or down. Stop the project: it does not bounce yet.
Steps 4-6 add blocks inside this repeat until loop. Step 7 adds blocks below it.
when green flag clicked say [] set [Left score] to 0 set [Right score] to 0 go to x: 0 y: 0 set [vx] to 4 set [vy] to (pick random -3 to 3) if ((vy) = 0) then set [vy] to 2 end wait 0.7 seconds repeat until (((Left score) = 5) or ((Right score) = 5)) change x by (vx) change y by (vy) end
Every green-flag click resets both scores, centers the ball, and serves it after a short pause.
Mine doesn't work
Ball not moving? A speed is 0, or you typed vx into a slot instead of dropping in the orange vx reporter.
Understand why
vx = 4 moves the ball 4 steps right on every loop. A negative value moves it left. Flipping the sign later reverses direction without changing speed.
Bounce off the top and bottom
GoalThe top and bottom are walls. The left and right sides stay open so a missed ball can score.
- Inside Ball's repeat until loop, right after change x and change y, add these two checks.
- Build each 0 - vy with the green subtract block and the orange vy reporter. Do not type vy into the number box.
- Do not use if on edge, bounce. It would bounce the ball off the left and right sides too, so nobody could score.
- Run a few serves. The ball should bounce at the top and bottom but still pass through the paddles for now.
if ((y position) > 173) then set y to 173 set [vy] to (0 - (vy)) end if ((y position) < -173) then set y to -173 set [vy] to (0 - (vy)) end
The ball stays inside the court and bounces smoothly off the top and bottom, but not off the sides.
Mine doesn't work
Ball shaking at a wall? The set y block or the 0 - vy flip is missing. Check both checks, and the minus sign on -173.
Remove if on edge, bounce. Use only the explicit y wall checks, then the x scoring checks.
Understand why
The ball has radius 7, so its center touches a wall at 180 - 7 = 173. Moving it back to 173 stops it bouncing twice while it is past the edge.
Return the ball with a paddle
GoalA hit should send the ball back once, not flip it back and forth while it overlaps the paddle.
- Add these two checks below the wall checks, still inside Ball's loop.
- Pick Left Paddle or Right Paddle in the light-blue touching block. Join it to the speed check with a green and block.
- After a left-paddle hit, set x to -196. After a right-paddle hit, set x to 196. That puts the ball just clear of the paddle.
- Click the flag and rally. A paddle should only return a ball that is moving toward it.
if (<touching [Left Paddle]?> and ((vx) < 0)) then set x to -196 set [vx] to (0 - (vx)) end if (<touching [Right Paddle]?> and ((vx) > 0)) then set x to 196 set [vx] to (0 - (vx)) end
Predict, then testWhat happens if you take out the vx < 0 check? Predict it, watch the left paddle, then put it back.
Both paddles return the ball cleanly. Missing lets the ball fly off that player's side.
Mine doesn't work
Ball stuck or jittering? The speed check is backwards. Left paddle needs vx < 0. Right paddle needs vx > 0.
Use touching AND vx < 0 on the left, touching AND vx > 0 on the right. Reset x to -196 or 196, then negate vx. Keep the supplied sprite sizes.
Understand why
The speed check stops a ball that is already leaving from bouncing again. 196 comes from the paddle center (210) minus half its width (6), the ball radius (7), and 1 step of space.
Score a point and serve again
GoalA miss should add one point, then put the ball back in the middle for the next rally.
- Add these scoring checks at the bottom of Ball's loop, after both paddle checks.
- Past x 230 on the right? Left score goes up. Past -230 on the left? Right score goes up. Use change score by 1, not set score to 1.
- Each branch gets the full reset: center the ball, set vx, pick a new vy, wait 0.7. A right-side miss serves right (vx 4); a left-side miss serves left (vx -4).
- Move a paddle out of the way on purpose. Watch the score change, the ball reset, and the short pause.
if ((x position) > 230) then
change [Left score] by 1
go to x: 0 y: 0
set [vx] to 4
set [vy] to (pick random -3 to 3)
if ((vy) = 0) then
set [vy] to 2
end
wait 0.7 seconds
end
if ((x position) < -230) then
change [Right score] by 1
go to x: 0 y: 0
set [vx] to -4
set [vy] to (pick random -3 to 3)
if ((vy) = 0) then
set [vy] to 2
end
wait 0.7 seconds
endEach miss gives exactly one point to the other player. Scores stay between serves, and paddles still move during the pause.
Mine doesn't work
Score shooting up? The ball reset is missing from that branch. Score stuck at 1? You used set instead of change.
Set both scores to 0 only at green-flag startup. After a miss, change the opponent's score by 1 and move the ball to the center inside that same if branch.
Understand why
Moving the ball to x 0 right away ends the miss. Without that reset, the loop would award a point on every pass.
Finish a first-to-five match
GoalYour loop already stops when someone reaches 5. Now announce the winner and end the game.
- Find the bottom of Ball's repeat until loop. Snap the blocks below underneath it, outside the loop.
- Build the if/else with a green = block and the orange Left score reporter. Put a purple say block in each branch.
- Finish with stop all from the gold Control category.
- Test both winners. After a win, clicking the green flag must clear the message, reset both scores, and move all three sprites back.
These blocks go outside the loop, snapped to its bottom edge. Nothing moves out of the loop.
if ((Left score) = 5) then say [Left player wins! Click the green flag to play again.] else say [Right player wins! Click the green flag to play again.] end stop [all]
Compare your complete Ball script
Every snippet in the right order. The downloadable completed game is built from this same script.
when green flag clicked
say []
set [Left score] to 0
set [Right score] to 0
go to x: 0 y: 0
set [vx] to 4
set [vy] to (pick random -3 to 3)
if ((vy) = 0) then
set [vy] to 2
end
wait 0.7 seconds
repeat until (((Left score) = 5) or ((Right score) = 5))
change x by (vx)
change y by (vy)
if ((y position) > 173) then
set y to 173
set [vy] to (0 - (vy))
end
if ((y position) < -173) then
set y to -173
set [vy] to (0 - (vy))
end
if (<touching [Left Paddle]?> and ((vx) < 0)) then
set x to -196
set [vx] to (0 - (vx))
end
if (<touching [Right Paddle]?> and ((vx) > 0)) then
set x to 196
set [vx] to (0 - (vx))
end
if ((x position) > 230) then
change [Left score] by 1
go to x: 0 y: 0
set [vx] to 4
set [vy] to (pick random -3 to 3)
if ((vy) = 0) then
set [vy] to 2
end
wait 0.7 seconds
end
if ((x position) < -230) then
change [Right score] by 1
go to x: 0 y: 0
set [vx] to -4
set [vy] to (pick random -3 to 3)
if ((vy) = 0) then
set [vy] to 2
end
wait 0.7 seconds
end
end
if ((Left score) = 5) then
say [Left player wins! Click the green flag to play again.]
else
say [Right player wins! Click the green flag to play again.]
end
stop [all]The first player to five sees a winner message, everything stops, and the green flag starts a clean new match.
Mine doesn't work
Winner shows straight away? The finish blocks are inside the loop, or a 5 is wrong. Check where they sit first.
Use repeat until (Left score = 5 OR Right score = 5). All rally code goes inside. The winner if/else and stop all go underneath, outside the loop.
Understand why
The repeat until condition ends the rally as soon as either score is 5. The winner check sits below the loop, so it runs once, after the game ends.
Test it, save it, make it yours
GoalA game is finished when it works every time and you can open it again later.
- Run the test checklist below, including a win by each player and a fresh restart.
- Choose File > Save to your computer. Keep the .sb3 somewhere you can find it, and make a spare copy before experimenting.
- Open a new editor tab, load your saved file, and play again.
- Pick one challenge from Make it yours. Change one thing at a time and rerun the tests.
- Sharing is optional. Never put your full name, school, or contact details in a shared project.
Your saved .sb3 opens with the same working game, and you can explain what vx, vy, and the win condition do.
Mine doesn't work
Double-clicking the file does nothing? Open Scratch first, then File > Load from your computer.
Open the Scratch editor, choose File > Load from your computer, and select the .sb3 file. Redownload it if necessary; do not unzip or rename its internal files.
Understand why
Reopening the file proves your work is saved. A test list helps you tell a real improvement from a new bug.
Test your finished game
Run these checks after you finish and after every change. A working game passes all seven.
Click the green flag twice during a match.
Both scores reset to 0; paddles and ball reset; one ball script runs.
Hold W/S, then each arrow key.
The correct paddle moves and stays completely on the stage.
Let the ball hit the top and bottom.
It reverses vertical direction without shaking or sticking.
Return the ball with each paddle.
It reverses horizontal direction once and continues into the court.
Miss on the right, then miss on the left.
The opposite player gains exactly one point on each miss.
Let each player reach five in separate games.
The correct winner is announced and all movement stops.
Restart after a win; save and reopen the file.
The winner message clears, both scores reset, and the game remains playable.
Find the symptom. Fix the cause.
Check the smallest likely mistake before rebuilding a whole script.
The keys do nothing, or the page scrolls.
Likely cause: The browser is not sending keyboard input to the Scratch stage.
Try this: Click the stage, then try the controls again. Make sure a sprite-name or number field is not focused. Check each script is on the correct paddle.
One player stops moving when several keys are held.
Likely cause: Some keyboards cannot register certain simultaneous key combinations.
Try this: Try a different keyboard or change one player's keys. Keep a record of the replacement controls so both players know what to use.
The ball gets stuck inside a paddle.
Likely cause: The direction guard or the position reset is missing.
Try this: Use touching AND vx < 0 on the left, touching AND vx > 0 on the right. Reset x to -196 or 196, then negate vx. Keep the supplied sprite sizes.
The ball bounces from the sides instead of scoring.
Likely cause: A general edge-bounce block is handling the left and right boundaries.
Try this: Remove if on edge, bounce. Use only the explicit y wall checks, then the x scoring checks.
A miss gives many points, or every point resets the score.
Likely cause: A reset is missing or placed in the wrong part of the script.
Try this: Set both scores to 0 only at green-flag startup. After a miss, change the opponent's score by 1 and move the ball to the center inside that same if branch.
The game never ends, or ends immediately.
Likely cause: The winning condition or its loop placement is incorrect.
Try this: Use repeat until (Left score = 5 OR Right score = 5). All rally code goes inside. The winner if/else and stop all go underneath, outside the loop.
The downloaded project will not open.
Likely cause: The file may be opened with the wrong application or may not be an intact .sb3.
Try this: Open the Scratch editor, choose File > Load from your computer, and select the .sb3 file. Redownload it if necessary; do not unzip or rename its internal files.
Now make it yours
Keep a working copy. Choose one change, predict what it will do, then test it.
Design a new court
Change colors and add a title. Keep paddle dimensions, centers, and ball size unchanged at first.
You have succeeded when: All acceptance tests still pass, with your own visual identity.
Add a winning-score setting
Create a Target score variable and replace every hard-coded winning value consistently. Try three, then seven.
You have succeeded when: Either player wins exactly at the chosen target, including after restarting.
Build a computer opponent
Replace one paddle's key checks with a rule that moves toward the ball. Cap its movement below the human paddle's eight-unit step.
You have succeeded when: You can play alone, the paddle stays in bounds, and it does not teleport to the ball.
The wall and paddle numbers assume the supplied sprites and a speed of 4. A much faster ball can jump straight past a thin paddle. Retest collisions after any change.
Files & downloads
To open an .sb3, start Scratch, then choose File > Load from your computer.
Sources
- Scratch: Create a Pong Game
Official introduction to Pong concepts. Its older, single-paddle tutorial differs from this original two-player implementation.
- Scratch Help Center: saving your project
Local save/load workflow and account-related saving guidance.
- Scratch VM: Scratch 3 serialization
Native .sb3 project, block, and asset structure used by the downloads.
- Original Vilros Scratch Ping Pong article
Original topic reference. This guide is a new implementation, not a claim to reproduce the old article's code.
Keep the momentum going.
Try another project and keep building your skills.