Build a Catching Game using Pygame Zero
Pygame zero is a tool used for education and is suitable for anyone who is starting to learn to create games using Python. So let’s start by making a little catching game :)
You can install pygame zero using pip as shown
pip install pgzero
Hello Pygamezero!
To start with pygamezero copy the following code to a file catching_game.py
import pgzrunWIDTH = 800
HEIGHT = 600
pgzrun.go()
This will create a screen of WIDTH 800 and HEIGHT 600.
To run this , type the following in terminal
python catching_game.pyPrepare
Before starting to code the rest, lets collect the images and sounds needed. In your main project folder create a folder named images and add apple.png, skybg.png and basket.png to it. I have added 2 sound effects also to sounds directory
Catching-Apple-Game-in-Pygamezero
├─ README.md
├─ chasingApple.py
├─ images
│ ├─ apple.png
│ ├─ basket.png
│ └─ skybg.jpg
└─ sounds
├─ gameover.wav
└─ pop.wavGitHub link to the images I have used is here. Feel free to download.
Now lets start to draw these images on the screen. Moving images on the screen are called Actors in pygamezero. We create two actors bowl and apple as shown.
'''
Draw Basket and Apple
'''import pgzrun
import randomWIDTH = 800
HEIGHT = 600
bowl = Actor('basket')
apple = Actor('apple')pgzrun.go()
After creating the Actors , we need to draw them on the screen. draw() is an inbuilt function in Pygamezero which is called when it needs to redraw the game window when an event is triggered.
'''
Draw Basket and Apple
'''import pgzrun
import randomWIDTH = 800
HEIGHT = 600
bowl = Actor('basket')
apple = Actor('apple')
def draw():
screen.clear()
screen.blit('skybg', (0, 0))
bowl.draw()
apple.draw()pgzrun.go()
screen is a built-in that represents the window display. screen.blit(image,(left,top)) helps to draw an image on the screen in a position given by (left,top).
Movement of Basket
Before moving the basket, lets keep the basket in a starting position. We can adjust x and y coordinates of the basket. WIDTH//2 indicates the middle of the screen. and HEIGHT- 40 is at the bottom of the screen.
move_basket() function is used to move the basket as the user presses left and right arrow in keyboard. To control which keys are pressed on the keyboard, you can query the attributes of the keyboard built-in inside an if condition.
Finally we add update() function which is again a builtin function that will be called repeatedly, 60 times a second. So we call move_basket() function in update to keep the basket movement show on screen.
'''
Movement of Basket and Apple
'''import pgzrun
import randomWIDTH = 800
HEIGHT = 600
basket = Actor('basket')
apple = Actor('apple')#position the basket
basket.x = WIDTH // 2
basket.y = HEIGHT - 40def move_basket():
"""move the basket"""
if keyboard.left:
basket.x -= 5
elif keyboard.right:
basket.x += 5def draw():
screen.clear()
screen.blit('skybg', (0, 0))
basket.draw()
apple.draw()def update():
move_basket()pgzrun.go()
Falling of Apple
Now lets make the apples fall.
- We define
position_fruit()function. Like we position the basket, we need to fix the position of apples too. So apples are falling from random positions, So we need to create apple.x at random position on top of the screen random number between (40,width-40) is anywhere in the screen. apple.y is -100 which is above the top of the screen.
2. And then we add an if condition in update(). This will check the y value of apple, if it goes down the screen you call position_fruit() again to reposition the apple to top of the screen(at random x) otherwise the apple. y is continuously decremented by 10 to make the falling effect.
import pgzrun
import randomWIDTH = 800
HEIGHT = 600
bowl = Actor('basket')
apple = Actor('apple')
basket.x = WIDTH // 2
basket.y = HEIGHT - 40def position_fruit():
apple.x = random.randint(40, WIDTH - 40)
apple.y = -100def move_basket():
"""move the basket"""
if keyboard.left:
basket.x -= 5
elif keyboard.right:
basket.x += 5def draw():
screen.clear()
screen.blit('skybg', (0, 0))
basket.draw()
apple.draw()def update():
move_basket()
if apple.y > HEIGHT + 40:
position_fruit()
else:
apple.y += 10
pgzrun.go()
Collision
Now lets see what happens when the basket catches an apple.
- We initialize a variable named score = 0.
2. Pygamezero has a cool method called colliderect()method for actors which returns True if two actors collide each other. Score is incremented by one (printing the score in terminal to verify) if collision occurs and immediately position_fruit() is called to reposition the apple.
'''score variable incremented and printed in terminal'''import pgzrun
import randomWIDTH = 800
HEIGHT = 600
bowl = Actor('basket')
basket.x = WIDTH // 2
basket.y = HEIGHT - 40
score = 0apple = Actor('apple')
def position_fruit():
apple.x = random.randint(40, WIDTH - 40)
apple.y = -100def draw():
screen.clear()
screen.blit('skybg', (0, 0))
basket.draw()
apple.draw()def move_basket():
if keyboard.left:
basket.x -= 5
elif keyboard.right:
basket.x += 5def update():
global score
move_basket()
if apple.y > HEIGHT + 40:
position_fruit()
else:
apple.y += 10
if apple.colliderect(bowl):
score += 1
print(score)
position_fruit()
pgzrun.go()
Display Score
Now lets display the score in the screen itself. Also lets add a game timer. I believe the drawScore() function is self explanatory :) else check the documentation here .
Also we are initializing a game_timer variable to display which we will be discussing soon.
'''Display Score'''import pgzrun
import randomWIDTH = 800
HEIGHT = 600
bowl = Actor('basket')
bowl.x = WIDTH // 2
bowl.y = HEIGHT - 40score = 0
game_timer = 10apple = Actor('apple')
def position_fruit():
apple.x = random.randint(40, WIDTH - 40)
apple.y = -100def drawScore():
screen.draw.text("score: " + str(score), (45, 30))
screen.draw.text("Time: " + str(round(game_timer)), (45, 60))def draw():
screen.clear()
screen.blit('skybg', (0, 0))
bowl.draw()
apple.draw()
drawScore()def move_basket():
if keyboard.left:
bowl.x -= 5
elif keyboard.right:
bowl.x += 5def update():
global score
global game_timer
move_basket()
if apple.y > HEIGHT + 40:
position_fruit()
else:
apple.y += 10
if apple.colliderect(bowl):
score += 1
print(score)
position_fruit()
pgzrun.go()
Game Over
Finally to stop the game we need some criteria. In this simple game I have added a timer of 10 seconds.
- Initialize game_timer = 10 and a boolean variable is_game_over = False to check if the game is over
- Inside update() , if game_timer<0: stop the game by making is_game_over = True.(I have added a sound to play when game is over. check this if you want to learn more)
- if game is not over every time update() is called game_timer is decremented by 0.017 which is approximately 1/60.(Remember update() is called 60 times in a seconds, hence the logic)
- And finally in draw_score(), GAME OVER is displayed when is_game_over == True
import pgzrun
import randomWIDTH = 800
HEIGHT = 600
basket = Actor('basket')
basket.x = WIDTH // 2
basket.y = HEIGHT - 40apple = Actor('apple')is_game_over = False
game_timer = 10
score = 0def position_fruit():
apple.x = random.randint(40, WIDTH - 40)
apple.y = -100def draw_score():
screen.draw.text("score: " + str(score), (45, 30))
screen.draw.text("Time: " + str(round(game_timer)), (45, 60))
if is_game_over:
display_text = "Game Over\nScore " + str((score))
position=((WIDTH//2)-100, (HEIGHT//2))
screen.draw.text(display_text,position, fontsize=60, color=(255, 255, 255))def move_basket():
if keyboard.left:
basket.x -= 5
elif keyboard.right:
basket.x += 5def apple_fall():
if apple.y > HEIGHT + 40:
position_fruit()
else:
apple.y += 10
check_collision() def check_collision():
global score
if apple.colliderect(basket):
sounds.pop.play()
score += 1
position_fruit()def draw():
global game_timer,isgame
screen.clear()
screen.blit('skybg', (0, 0))
draw_score()
basket.draw()
apple.draw()def update():
global game_timer,is_game_over
if not is_game_over:
move_basket()
apple_fall()
if game_timer<=0:
sounds.gameover.play()
is_game_over = True
else:
game_timer -= 0.017position_fruit()
pgzrun.go()
Full code with images and sound can be viewed here:
https://github.com/soumyasomasundaran/Catching-Apple-Game-in-Pygamezero
