Scratch - Pong
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.

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.