Lets recreate the classic pong game. The game has a simple β€œtennis like” game feature, where both the user and computer controls a paddle and must hit the ball land avoid having the ball touching their side of the screen.

Scratch Pong Result

Unsure where the blocks should be placed? Look at the header, such as πŸ€– Position, that means those blocks is for the Computer Sprite

Get started

Visit Scratch and Create a new project

Start by creating the following sprites and variables for our game:

Sprites

😎 Player Sprite (I used the β€˜Paddle’ sprite and changed it’s direction to β€˜0’)

πŸ€– Computer Sprite (I used the β€˜Paddle’ sprite and changed it’s direction to β€˜0’)

⚽ Ball Sprite (I used the β€˜Ball’ sprite and changed it’s size to β€˜50’)

Variables

🚩 ball-y Variable

🚩 computer-y Variable

🚩 bounce Variable

🚩 player-score Variable

🚩 computer-score Variable

🚩 difficulty Variable

😎 Player

😎 Position

The 😎 Player paddle should be on the left side of the screen.

when flag clicked
go to x: (-230) y: (0)

😎 Controls

The 😎 Player is controlled with the mouse.
We are going to change the sprite y position so it always is the same as the mouse y position.

when flag clicked
go to x: (-230) y: (0)
forever
set y to (mouse y)

Everything inside our forever block is going to run over and over until the game is stopped.

⚽ Ball

⚽ Position

We want the ⚽ Ball to always start in the center of the screen.

when flag clicked
go to x: (0) y: (0)

⚽ Direction

The ball is first served to the player, so the ball direction should move towards the player’s side of the screen.

when flag clicked
go to x: (0) y: (0)
point in direction (-90)

⚽ Movement

The ball should now start moving. 16 is the speed of the ball.

when flag clicked
go to x: (0) y: (0)
point in direction (-90)
forever
move (16) steps

⚽ Bounce

To keep the ball moving, we are going to make it bounce when it hits the edge of the screen.

when flag clicked
go to x: (0) y: (0)
point in direction (-90)
forever
move (16) steps
if on edge, bounce

⚽ Hit Player Paddle

Lets make it possible for the player to hit the ball with their paddle. To separate the logic, lets make our own block.

define check-hit

We only want to detect hit when the ball is moving towards the player’s side of the screen (to the left).

define check-hit
if <(direction) < (0)> then
if <touching (Player v)> then

Change the rotation by 180 degrees, that will make the ball go from left to right.

define check-hit
if <(direction) < (0)> then
if <touching (Player v)> then
turn cw (180) degrees

Include the check-hit block in our forever loop.

when flag clicked
go to x: (0) y: (0)
point in direction (-90)
forever
move (16) steps
if on edge, bounce
check-hit :: custom

⚽ Control where the ball should go

In pong you should be able to control where you want the ball to move. This is done by checking where the ball hits the paddle, and we can do so by calculating the distance from the mouse y and ball y positions.

Store the result in our 🚩 bounce variable, place it right after our if block

if <(direction) < (0)> then
set [bounce v] to ((mouse y) - (y position))

Now update the code where we change the direction, so it adds the 🚩 bounce variable to 180.

turn cw ((180) + (bounce)) degrees

check-hit block:

define check-hit
if <(direction) < (0)> then
set [bounce v] to ((mouse y) - (y position))
if <touching (Player v)> then
turn cw ((180) + (bounce)) degrees

⚽ Store the ball y position

Before we make our computer logic, we are going update our 🚩 ball-y variable.

when flag clicked
go to x: (0) y: (0)
point in direction (-90)
forever
move (16) steps
if on edge, bounce
check-hit :: custom
set [ball-y v] to (y position)

πŸ€– Computer

We want the πŸ€– Computer to start on the right side of the screen

when flag clicked
go to x: (230) y: (0)

πŸ€– Movement

The πŸ€– Computer should always chase the ball, so lets make a forever loop that checks if it should move up or down.

when flag clicked
go to x: (230) y: (0)
forever
if <(ball-y) > (y position)> then
change y by (5)
else
change y by (-5)
end

The πŸ€– Computer now follows the ball. Let’s store the computer y position, so we can make identical bounce behavior for when the ball hits the computer.

when flag clicked
go to x: (230) y: (0)
forever
if <(ball-y) > (y position)> then
change y by (5)
else
change y by (-5)
end
set [computer-y v] to (y position)

⚽ Ball

⚽ Hitting the Computer

Lets first update our check-hit block and change our if block with a if else block.

define check-hit
if <(direction) < (0)> then
set [bounce v] to ((mouse y) - (y position))
if <touching (Player v)> then
turn cw ((180) + (bounce)) degrees
else
end

Lets first calculate the 🚩 bounce variable using the position of the computer.

define check-hit
if <(direction) < (0)> then
set [bounce v] to ((mouse y) - (y position))
if <touching (Player v)> then
turn cw ((180) + (bounce)) degrees
else
set [bounce v] to ((y position) - (computer-y))
end

And then add same same logic as when we touch the player, except we are going to check if we touch the computer.

define check-hit
if <(direction) < (0)> then
set [bounce v] to ((mouse y) - (y position))
if <touching (Player v)> then
turn cw ((180) + (bounce)) degrees
else
set [bounce v] to ((y position) - (computer-y))
if <touching (Computer v)> then
turn cw ((180) + (bounce)) degrees
end

πŸ€– Computer

πŸ€– Smooth movement

You might have noticed the the movement of the computer ain’t smooth, it jumps back and forth trying to match the position of the 🚩 ball-y variable.

To avoid this, we are going to make a if block that checks if the distance is larger than the steps we move (5). The abs function ensures values is always positive, that is abs(-5) = 5 and abs(100) = 100 and abs(-200) = 200.

First calculate the distance

((ball-y) - (y position))

Then make sure it is positive, using abs

([abs v] of ((ball-y) - (y position)))

Then check if it is larger than the steps we move (5)

([abs v] of ((ball-y) - (y position))) > (5)

Now create a new if block and put it around or existing logic.

when flag clicked
go to x: (230) y: (0)
forever
if <([abs v] of ((ball-y) - (y position))) > (5)> then
if <(ball-y) > (y position)> then
change y by (5)
else
change y by (-5)
end
set [computer-y v] to (y position)

⚽ Ball

⚽ Score points

Somebody has to win, and might as well be you. Lets make it possible for the ball to detect when it hit either the player or computer side of the screen.

Create a new block check-scoring

define check-scoring

and add it into our forever loop, right before we detect if the ball should bounce on the edge.

when flag clicked
go to x: (0) y: (0)
point in direction (-90)
forever
move (16) steps
check-scoring :: custom
if on edge, bounce
check-hit :: custom
set [ball-y v] to (y position)

⚽ Computer scoring

To detect if the ball is on the player’s side of the screen, we can use:

<(x position) < (-225)>

But we also need to make sure that the ball is actually moving towards the player’s side of the screen:

<(direction) < (0)>

Use the and operator, so we can check for both of them:

<<(direction) < (0)> and <(x position) < (-225)>>

Place the check in a if block in our new check-scoring block.

define check-scoring
if <<(direction) < (0)> and <(x position) < (-225)>> then

and then increase the 🚩 computer-score variable by 1

define check-scoring
if <<(direction) < (0)> and <(x position) < (-225)>> then
change [computer-score v] by (1)

⚽ Player scoring

The player scoring logic is almost identical to the computer scoring logic. We just need to check if the direction is now moving towards the computer’s side of the screen

<(direction) > (0)>

and that x position is now on the right side of the screen.

<(x position) > (225)>

and of course incrementing the 🚩 player-score variable by 1

change [player-score v] by (1)

Place all the logic in a new if block right after the first if bvlock.

define check-scoring
if <<(direction) < (0)> and <(x position) < (-225)>> then
change [computer-score v] by (1)
end
if <<(direction) > (0)> and <(x position) > (225)>> then
change [player-score v] by (1)
end

⚽ Too much up and down bouncing

You might have noticed by now, that sometimes the ball gets stuck in bouncing too much up and down, and it takes forever move across the screen. This can fixed by ensuring the ball can’t move in directions that is in the range (-40) to (40), (140) to (180) and (-140) to (-180)

First Create a new block direction-clamp

define direction-clamp

and add it to the forever loop, right after check-hit

when flag clicked
go to x: (0) y: (0)
point in direction (-90)
forever
move (16) steps
check-scoring :: custom
if on edge, bounce
check-hit :: custom
direction-clamp :: custom
set [ball-y v] to (y position)

Then We are going to check in intervals of 40 using the following blocks:

<(direction) > (?)>
<(direction) < (?)>

Check both using and operator

<<(direction) > (?)> and <(direction) < (?)>>

Use them in if block and update the direction

if <<(direction) > (?)> and <(direction) < (?)>> then
point in direction (?)

The first range (0) to 40 will look like this (Notice subtract 1, so it’s -1, that is to include the 0 since we are using > operator)

if <<(direction) > (-1)> and <(direction) < (40)>> then
point in direction (40)

Now add the new if block with the logic to our direction-clamp block.

define direction-clamp
if <<(direction) > (-1)> and <(direction) < (40)>> then
point in direction (40)

Do the same for the remaining intervals

define direction-clamp
if <<(direction) > (-1)> and <(direction) < (40)>> then
point in direction (40)
end
if <<(direction) > (-40)> and <(direction) < (1)>> then
point in direction (-40)
end
if <<(direction) > (140)> and <(direction) < (181)>> then
point in direction (140)
end
if <<(direction) > (-140)> and <(direction) < (-181)>> then
point in direction (-140)
end

🎭 Stage

🎭 Reset

Lets make sure that whenever the green flag πŸ’š is pressed we reset the scores. Lets place this logic in the stage, that means NOT in the ⚽ Ball, πŸ€– Computer and 😎 Player logic.

when flag clicked
set [player-score v] to (0)
set [computer-score v] to (0)

🎭 Difficulty

Maybe the game is a little too easy, lets make it possible to control the difficulty. First lets always see the difficulty to 1 when the game starts.

when flag clicked
set [player-score v] to (0)
set [computer-score v] to (0)
set [difficulty v] to (0)

Then lets increase or decrease the difficulty using the up and down arrow keys

when [up arrow] key pressed
change [difficulty v] by (0.1)
when [down arrow] key pressed
change [difficulty v] by (-0.1)

πŸ€– Computer Difficulty

For our pong game, the difficulty should change how fast the computer can move. Instead of always moving the computer by 5, we will now multiply it with our difficulty, and we can do so using this block

(5) * (difficulty)

Now we should update our current πŸ€– Computer logic, that looks like this:

when flag clicked
go to x: (230) y: (0)
forever
if <([abs v] of ((ball-y) - (y position))) > (5)> then
if <(ball-y) > (y position)> then
change y by (5)
else
change y by (-5)
end
set [computer-y v] to (y position)

and make it look like this:

when flag clicked
go to x: (230) y: (0)
forever
if <([abs v] of ((ball-y) - (y position))) > ((5) * (difficulty))> then
if <(ball-y) > (y position)> then
change y by ((5) * (difficulty))
else
change y by ((-5) * (difficulty))
end
set [computer-y v] to (y position)

⚽ Sounds

⚽ Ping-Pong

If you play the original pong game you will hear a ping-pong sound whenever the ball hits the paddle. To do such use two different sounds.

start sound [A Piano v]
start sound [B Piano v]

Add them to the if-block for when the ⚽ Ball touches the 😎 Player or the πŸ€– Computer. It will look like this:

define check-hit
if <(direction) < (0)> then
set [bounce v] to ((mouse y) - (y position))
if <touching (Player v)> then
turn cw ((180) + (bounce)) degrees
start sound [A Piano v]
else
set [bounce v] to ((y position) - (computer-y))
if <touching (Computer v)> then
turn cw ((180) + (bounce)) degrees
start sound [B Piano v]
end

⚽ Score!

Find two different sounds to when the 😎 Player or the πŸ€– Computer scores.

start sound [Connect v]
start sound [Disconnect v]

Add them to the if-block for when the 😎 Player or the πŸ€– Computer scores. Like this:

define check-scoring
if <<(direction) < (0)> and <(x position) < (-225)>> then
change [computer-score v] by (1)
start sound [Disconnect v]
end
if <<(direction) > (0)> and <(x position) > (225)>> then
change [player-score v] by (1)
start sound [Connect v]
end

πŸ’‘ Ideas

Your Pong game is now done. But you can always add more! Maybe you could try:

  • πŸŒ† Add a background, maybe theme all your sprites, so they fit the background.
  • ✨ Add a Trail using clones spawned at the ball position, which fades away over time .
  • 🎊 Add Firework when the ball hits the paddle by spawning multiple clones, that has random color, direction and speed.
  • 🎼 Add background music by using a forever block that keeps playing a sound over and over.

Updated: