# Build your own Scratch Pong game

Turn three simple sprites into a two-player arcade game. Build the controls, make the ball bounce, keep score, and play a first-to-five match.

Version 1.1 | Beginner-friendly | 60-90 min estimated build time

## 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.

## What you need

- **A computer (Required):** Any computer that can run the Scratch 3 web editor. A Raspberry Pi works too, but you do not need one.

- **Keyboard + mouse (Required):** Both players share one keyboard. Use a mouse or trackpad to drag blocks. Touch-only screens will not work.

- **Scratch 3 web editor (Free):** Runs in your browser. You do not need an account to save your project to your computer. https://scratch.mit.edu/projects/editor/

- **Starter project (Included):** The court, two paddles, the ball, and four variables, ready to go. You add all the code. /project-files/scratch-pong-starter.sb3

## 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.

## Stage and sprite dimensions

Stage: 480 x 360, x = -240..240, y = -180..180. Left Paddle: x=-210, y=0, 12 x 80. Right Paddle: x=210, y=0, 12 x 80. Ball: x=0, y=0, diameter 14. All sprites at 100% size; centers at costume centers.

## 1. Open your project workspace

Start with artwork that is already the right size. You will write all of the game code yourself.

1. Download the starter file with the button above, then open the Scratch web editor at scratch.mit.edu/projects/editor.

2. Choose File > Load from your computer and pick scratch-pong-starter.sb3. Loading replaces whatever was open, so save other work first.

3. You should see three sprites: Left Paddle, Right Paddle, and Ball. Click each one. The Code area should be empty.

4. Open the orange Variables category. Left score, Right score, vx, and vy should all be there. Only the two scores show on the stage.

5. Name your project, for example My First Pong Game. Keep this guide and the editor side by side.

**Why it works:** Everyone starts with the same sprites, so the numbers in later steps (like 140 and 196) fit your game exactly.

**Checkpoint:** Three named sprites are visible, both scores read 0, and no sprite has any code yet.

**If it does not work:** Code already there? You loaded the completed game, not the starter. Reload the starter file.

## 2. Give each player a paddle

The left player uses W and S. The right player uses the up and down arrows. Paddles only move up and down.

1. 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.

2. Select Right Paddle and build its stack. It starts at x 210 and uses the arrow keys.

3. Everything below go to x goes inside forever. The yellow green-flag block stays on top.

4. Click the green flag, click the stage, then try all four keys. Click the red stop sign when you are done.

### Left Paddle

```text
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
end
```

### Right Paddle

```text
when 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
end
```

**Predict:** What happens if you change both 8s to 4? Predict it, try it, then change them back.

**Why it works:** 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.

**Checkpoint:** 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.

**If it does not 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.

## 3. Make the ball move

Give the ball two speeds: vx for left and right, vy for up and down. Then start the main game loop.

1. Select Ball and build this stack. The setup blocks run once, before the loop.

2. 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.

3. Until someone reaches 5, repeat until keeps looping just like forever. You will not need to rebuild this loop later.

4. 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.

5. Click the flag. The ball waits, then moves right and up or down. Stop the project: it does not bounce yet.

### Ball

Steps 4-6 add blocks inside this repeat until loop. Step 7 adds blocks below it.

```text
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
```

**Why it works:** 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.

**Checkpoint:** Every green-flag click resets both scores, centers the ball, and serves it after a short pause.

**If it does not work:** Ball not moving? A speed is 0, or you typed vx into a slot instead of dropping in the orange vx reporter.

## 4. Bounce off the top and bottom

The top and bottom are walls. The left and right sides stay open so a missed ball can score.

1. Inside Ball's repeat until loop, right after change x and change y, add these two checks.

2. Build each 0 - vy with the green subtract block and the orange vy reporter. Do not type vy into the number box.

3. Do not use if on edge, bounce. It would bounce the ball off the left and right sides too, so nobody could score.

4. Run a few serves. The ball should bounce at the top and bottom but still pass through the paddles for now.

### Ball - inside the loop, after movement

```text
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
```

**Why it works:** 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.

**Checkpoint:** The ball stays inside the court and bounces smoothly off the top and bottom, but not off the sides.

**If it does not 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.

## 5. Return the ball with a paddle

A hit should send the ball back once, not flip it back and forth while it overlaps the paddle.

1. Add these two checks below the wall checks, still inside Ball's loop.

2. Pick Left Paddle or Right Paddle in the light-blue touching block. Join it to the speed check with a green and block.

3. 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.

4. Click the flag and rally. A paddle should only return a ball that is moving toward it.

### Ball - inside the loop, after wall bounces

```text
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:** What happens if you take out the vx < 0 check? Predict it, watch the left paddle, then put it back.

**Why it works:** 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.

**Checkpoint:** Both paddles return the ball cleanly. Missing lets the ball fly off that player's side.

**If it does not work:** Ball stuck or jittering? The speed check is backwards. Left paddle needs vx < 0. Right paddle needs vx > 0.

## 6. Score a point and serve again

A miss should add one point, then put the ball back in the middle for the next rally.

1. Add these scoring checks at the bottom of Ball's loop, after both paddle checks.

2. 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.

3. 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).

4. Move a paddle out of the way on purpose. Watch the score change, the ball reset, and the short pause.

### Ball - inside the loop, after paddle bounces

```text
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
```

**Why it works:** Moving the ball to x 0 right away ends the miss. Without that reset, the loop would award a point on every pass.

**Checkpoint:** Each miss gives exactly one point to the other player. Scores stay between serves, and paddles still move during the pause.

**If it does not work:** Score shooting up? The ball reset is missing from that branch. Score stuck at 1? You used set instead of change.

## 7. Finish a first-to-five match

Your loop already stops when someone reaches 5. Now announce the winner and end the game.

1. Find the bottom of Ball's repeat until loop. Snap the blocks below underneath it, outside the loop.

2. Build the if/else with a green = block and the orange Left score reporter. Put a purple say block in each branch.

3. Finish with stop all from the gold Control category.

4. Test both winners. After a win, clicking the green flag must clear the message, reset both scores, and move all three sprites back.

### Ball - attach under the loop

These blocks go outside the loop, snapped to its bottom edge. Nothing moves out of the loop.

```text
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]
```

**Why it works:** 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.

**Checkpoint:** The first player to five sees a winner message, everything stops, and the green flag starts a clean new match.

**If it does not work:** Winner shows straight away? The finish blocks are inside the loop, or a 5 is wrong. Check where they sit first.

## 8. Test it, save it, make it yours

A game is finished when it works every time and you can open it again later.

1. Run the test checklist below, including a win by each player and a fresh restart.

2. Choose File > Save to your computer. Keep the .sb3 somewhere you can find it, and make a spare copy before experimenting.

3. Open a new editor tab, load your saved file, and play again.

4. Pick one challenge from Make it yours. Change one thing at a time and rerun the tests.

5. Sharing is optional. Never put your full name, school, or contact details in a shared project.

**Why it works:** Reopening the file proves your work is saved. A test list helps you tell a real improvement from a new bug.

**Checkpoint:** Your saved .sb3 opens with the same working game, and you can explain what vx, vy, and the win condition do.

**If it does not work:** Double-clicking the file does nothing? Open Scratch first, then File > Load from your computer.

## Complete Ball script

```text
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]
```

## Test checklist

- [ ] Click the green flag twice during a match. Expected: Both scores reset to 0; paddles and ball reset; one ball script runs.

- [ ] Hold W/S, then each arrow key. Expected: The correct paddle moves and stays completely on the stage.

- [ ] Let the ball hit the top and bottom. Expected: It reverses vertical direction without shaking or sticking.

- [ ] Return the ball with each paddle. Expected: It reverses horizontal direction once and continues into the court.

- [ ] Miss on the right, then miss on the left. Expected: The opposite player gains exactly one point on each miss.

- [ ] Let each player reach five in separate games. Expected: The correct winner is announced and all movement stops.

- [ ] Restart after a win; save and reopen the file. Expected: The winner message clears, both scores reset, and the game remains playable.

## Troubleshooting

### The keys do nothing, or the page scrolls.
The browser is not sending keyboard input to the Scratch stage.

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.
Some keyboards cannot register certain simultaneous key combinations.

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.
The direction guard or the position reset is missing.

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.
A general edge-bounce block is handling the left and right boundaries.

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.
A reset is missing or placed in the wrong part of the script.

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.
The winning condition or its loop placement is incorrect.

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.
The file may be opened with the wrong application or may not be an intact .sb3.

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.

## Extension challenges

### Design a new court (Make it yours)
Change colors and add a title. Keep paddle dimensions, centers, and ball size unchanged at first.

Success: All acceptance tests still pass, with your own visual identity.

### Add a winning-score setting (Go further)
Create a Target score variable and replace every hard-coded winning value consistently. Try three, then seven.

Success: Either player wins exactly at the chosen target, including after restarting.

### Build a computer opponent (Stretch challenge)
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.

Success: You can play alone, the paddle stays in bounds, and it does not teleport to the ball.

## Sources

- [Scratch: Create a Pong Game](https://scratch.mit.edu/help/studio/tips/howto/pgame-intro/) - Official introduction to Pong concepts. Its older, single-paddle tutorial differs from this original two-player implementation.

- [Scratch Help Center: saving your project](https://mitscratch.freshdesk.com/en/support/solutions/articles/4000155650-why-can-t-i-save-my-project-) - Local save/load workflow and account-related saving guidance.

- [Scratch VM: Scratch 3 serialization](https://github.com/scratchfoundation/scratch-vm/blob/develop/src/serialization/sb3.js) - Native .sb3 project, block, and asset structure used by the downloads.

- [Original Vilros Scratch Ping Pong article](https://vilros.com/blogs/raspberry-pi-beginner-projects/scratch-ping-pong) - Original topic reference. This guide is a new implementation, not a claim to reproduce the old article's code.
