Akbar Ali
Posted on August 5, 2022
Introduction
I am making the famous Flappy bird game using python and it's library called 'pygame'. It is so simple to make and much addictive to play. It requires only 200 lines of codes. There is a web version of this game you can find at flappybird.io.
About flappy
Flappy Bird was a mobile game developed by Vietnamese video game artist and programmer Dong Nguyen (Vietnamese: Nguyễn Hà Đông), under his game development company, Gears. The game is a side-scroller where the player controls a bird, attempting to fly between columns of green pipes without hitting them. Nguyen created the game over the period of several days, using a bird protagonist that he had designed for a cancelled game in 2012.
Pygame
pygame is a Python wrapper for the SDL library, which stands for Simple DirectMedia Layer. SDL provides cross-platform access to your system’s underlying multimedia hardware components, such as sound, video, mouse, keyboard, and joystick. pygame started life as a replacement for the stalled PySDL project. The cross-platform nature of both SDL and pygame means you can write games and rich multimedia Python programs for every platform that supports them!
Install pygame using pip if you have already installed python.
pip install pygame
Import it into your python program and intialize
import pygame
pygame.init()
Project
Create a project folder named flappy
and create a python file named flappy.py
in it.
Assets
We need some sprite assets to make this game. The 3 bird sprites with animated wings, the green pipes, ground, background and the restart button. You can find the assets here
download the assets and keep it in a folder named img
.
So the file structure would look like this.
flappy
|
| -- img
|
-- bg.png
-- bird1.png
-- bird2.png
-- bird3.png
-- ground.png
-- pipe.png
-- restart.png
|
| -- flappy.py
Basic setup
start you code by importing required modules.
import pygame
from pygame.locals import *
import random
pygame.locals
module contains various constants used by pygame. We use random for generating random pipes through the sidescroller.
Initialize pygame
pygame.init()
Define screen height and width so we can create the window.
screen_width = 460
screen_height = 500
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Flappy Bird')
And finally we need a game loop to run until the player exits.
run = True
while run:
pass
Make sure to quit pygame at the end of the code
pygame.quit()
Now run the python program from your terminal.
python3 flappy.py
This will open a new blank window with the height and width we defined before. But now we cannot close the window except we interrupt the terminal. This is because we did not instruct the loop to break when the user closes the window and it will trigger the pygame.quit()
at the end of the code.
We have to loop through the pygame events and check if it's a closing event. Then make the run
to false
which will break the loop.
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
Now we will be able to close the window after running the program.
Background
Let's draw the background first. So import the bg
sprite from the img
folder and scale it according to the screen.
bg = pygame.image.load('img/bg.png')
bg = pygame.transform.scale(bg, (460, 420))
And inside the loop draw the bg using blit
function
# draw background
screen.blit(bg, (0,0))
also add the update function at the end of the loop
pygame.display.update()
Run the program now and you will see the background.
Ground
Import the ground image as we imported the background.
ground_img = pygame.image.load('img/ground.png')
ground_img = pygame.transform.scale(ground_img, (480, 80))
Also declare some variables to make the ground scroll.
# game variables
ground_scroll = 0
scroll_speed = 2
Inside the loop, right after drawing the ground draw the ground with ground_scroll
as it's x
value. Also update the ground_scroll
with scroll_speed
.
# draw ground
screen.blit(ground_img, (ground_scroll, 420))
ground_scroll -= scroll_speed
And we also need to reset the ground ground_scroll
to 0 after it passes 20
to get a continuous scroll.
if abs(ground_scroll) > 20:
ground_scroll = 0
FPS
Now the ground scrolls so fast and we have to control the fps. Otherwise fps may vary from computers to computers. So at the top, declare fps
and pygame clock
# fps control
clock = pygame.time.Clock()
fps = 60
Inside the loop, at the top call the tick
function using fps
variable.
clock.tick(fps)
Try the game and see the ground scrolls slowly.
Bird class
Now, let's create the bird class. In the bird class, we have a constructor where we receive the x, y and an update method.
class Bird(pygame.sprite.Sprite):
def __init__(self, x, y):
pass
def update(self):
pass
See we have derived the class from pygame.sprite.Sprite
. It's a simple base class for visible game objects.
Let's code the __init__
method.
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.images = []
self.index = 0
self.counter = 0
for num in range(1, 4):
img = pygame.image.load(f'img/bird{num}.png')
img = pygame.transform.scale(img, (35, 25))
self.images.append(img)
self.image = self.images[self.index]
self.rect = self.image.get_rect()
self.rect.center = [x, y]
self.vel = 0
self.clicked = False
Here we called the constructor of pygame.sprite.Sprite
at first. We have 3 sprites of bird images to animate. So, we loop 3 times and store each images to the images[]
. The index
variable is used to get the nth images at each frame. counter
is to control the animation fps. Also, we center the image to the x, y
using the rect
of the sprite. vel
is to set the velocity of the bird when the clicked = true
.
Now, we have the update
method to code.
def update(self):
# gravity
if flying == True:
self.vel += 0.2
if self.vel > 30:
self.vel = 0
if self.rect.bottom < 420:
self.rect.y += int(self.vel)
We coded the gravity functionality for the bird first. Make sure we have declared the flying
variable at the top of the code.
flying = False
We will add the velocity by 0.2 while the bird is flying and clamped the value to 30 because the bird don't need to go below the ground. The vel
variable will be added to rect.y
which leads to bring the bird downward like it's falling down.
Then, declare a game_over
variable at the top and append this code to the update
method.
if game_over == False:
# jump
if pygame.mouse.get_pressed()[0] == 1 and self.clicked == False:
self.clicked = True
self.vel = -5
if pygame.mouse.get_pressed()[0] == 0:
self.clicked = False
Check if it's not game over and the bird have to jump when the mouse pressed. We don't need to get continuous clicks, so we have to check the self.clicked
is false
. It it's time to jump, we set clicked
to true
and vel
to -5
which leads the bird upwards. We set the clicked
to false
when the mouse is released.
Now we have to animate the bird.
# handle animation
self.counter += 1
flap_cooldown = 5
if self.counter > flap_cooldown:
self.counter = 0
self.index += 1
if self.index >= len(self.images):
self.index = 0
self.image = self.images[self.index]
We set a variable flap_cooldown
to 5 and will check if the counter
goes after it. Then, change the index
variable and update the sprite image according to the index
. Make sure that index
is not greater than the length of the images. If it is, set it to 0.
At last, we will rotate the bird according to the velocity.
# rotate the bird
self.image = pygame.transform.rotate(self.images[self.index], self.vel * -2)
Make sure the above all codes are indented inside the game_over == False
condition. And when the game_over == true
we have to point the bird down like it's falling down quickly. So, right after the above condition, code this.
else:
self.image = pygame.transform.rotate(self.images[self.index], -90)
Now, our bird class is complete. let's draw the bird inside the loop. But, before that, we have to create a class group of bird right above the loop.
bird_group = pygame.sprite.Group()
And add a new Bird
object to the group.
flappy = Bird(100, int(screen_height/2))
bird_group.add(flappy)
We do this because it's easy to draw the sprite.Group
class of pygame
because it has a default draw
method itself.
Jump into the loop and call the draw
and update
method of the bird group.
# draw bird
bird_group.draw(screen)
bird_group.update()
Make sure we put this code after drawing the bg
and ground
, because we need the bird at the top of them.
Also add this code in the for event in pygame.event.get()
loop to make the flying = true
.
if event.type == pygame.MOUSEBUTTONDOWN and flying == False and game_over == False:
flying = True
This will trigger the bird to fly when we click the mouse button for the first time. But won't start the game when open it.
One more update to do. we have to cover the ground_scroll
update we coded before inside a condition, because we don't have to scroll the ground if the game is not started yet.
if game_over == False and flying == True:
# scroll ground
ground_scroll -= scroll_speed
if abs(ground_scroll) > 20:
ground_scroll = 0
Now everything will start moving after we click the mouse button for the first time. Try the game now.
Conclusion
Hope you loved this post and enjoyed making flappy together. I will get back to you soon with another post where we add more functionalities to the game. Comment your opinions and doubts.
Second part: Part-1
Posted on August 5, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.