Create a Flappy Bird Clone With Python P9

Posted in python tutorials -

This is one part of a multi-part tutorial. To see other posts in the same series, please click below:

Part 1 - Setup virtualenv

Part 2 - Setup Pygame

Part 3 - Start making game

Part 4 - Make a “flapping” flappy bird

Part 5 - Make the bird fly

Part 6 - Pipe System

Part 7 - Kill the Bird

Part 8 - Add game logic

Part 9 - Finalize the game

In this part, we will finalize the game in some minor details.

Add base to the game

Inside the images directory, there’s one image called base.png, which represents the base of the screen, and should be blitz beneath the background.png.

The screen height should be the total height of background and base, while the width should stay the same. Since the base is more like a decoration than a real part of the game logic, you don’t have to adjust the drawing of anything to the new screen size.

Something like this will work:

base = pygame.image.load("images/base.png")
base_height = base.get_height()
full_height = height + base_height

size = (width, full_height)

screen = pygame.display.set_mode(size)

while 1:
    screen.blit(background, (0, 0))
    screen.blit(base, (0, height))

Pipe gap to variate

Have you noticed that since the beginning of the game, we have been using two pipes with fixed top_pipe_height (100 and 50)? That’s kind of boring, and the player can easily notice that we only have two pipes in our system. What we want to achieve is that the pipe’s top_pipe_height changes randomly every time it gets reset (i.e. moved back to the beginning position). This can be done quite easily with the random library in python3. You can choose one of several different functions in this library, but as we want to get one random integer in a range of number, random.randint seems to be the optimal choice.

The largest top_pipe_height can get is the actual value of pipe_height, because if top_pipe_height gets larger than that, we will tend to have a flying pipe due to a gap between the top screen and the toppipe. Similarly, the height of the botpipe should not be larger than pipe_height, which makes the smallest top_pipe_height can get height - GAP - pipe_height.

In reality, that range might be still too wide, which makes the game too difficult. You can narrow down the range if needed

While we’re at it, we can also remove the initial longitude, as we don’t need to customize that number now:

class Pipe:
    def __init__(self):
        self.top_pipe_height = random.randint(height - GAP - pipe_height, pipe_height)
        self.longitude = width + pipe_width
        self.initial_longitude = self.longitude
        self.visible = False

    ...
    
    def reset(self):
        self.top_pipe_height = random.randint(height - GAP - pipe_height, pipe_height)
        self.longitude = self.initial_longitude
        self.visible = False

Adding sound effects

In the assets that we downloaded in part 1, there’s a folder called audio, let’s move it out to the project’s main directory.

mv flappy-bird-assets-master/audio audio

A quick search for sound in the Pygame doc will show you this page. Basically the way pygame manages the sounds is similar to the way it manages images: first you load the audio file to a Sound object, then you can run sound.play(), which will play the sound. Since all flappy bird’s sounds are short, we probably don’t need stop() or any other functions.

First, let’s load up all the sounds. There are two versions of the same sound for each sound: wav and ogg. If you don’t know what OGG is, it is a free and good audio format file, but it might not run well on some system (it runs in mine, though). Though wav is a little bit heavier, it’s supposed to run in a wider range of system, so we will choose wav here (our audio files are not big anyway).

# Load sounds
point_sound = pygame.mixer.Sound("audio/point.wav")
swoosh_sound = pygame.mixer.Sound("audio/swoosh.wav")
hit_sound = pygame.mixer.Sound("audio/hit.wav")
die_sound = pygame.mixer.Sound("audio/die.wav")

Now our job is to add something_sound.play() into the places where it’s appropriate: swoosh_sound when the bird jumps, point_sound when it scores, hit_sound when it touches the pipe and die_sound when it dies.

Since hit_sound and die_sound go together, you may want to wait for hit_sound to finish before start playing die_sound. For that you can use:

pygame.time.delay(int(hit_sound.get_length()*1000))

By default, the .get_length() returns length in float seconds, bu pygame.time.delay requires an integer number of millisecond, hence the conversion.

Improve the coding style

Since the beginning of this series, we have been coding everything in the same file, and rarely change the file structure unless we feel a need. What we ended up with is a mixture of classes and global variables, and we don’t really have a good and consistent coding style. That’s normally how it goes when we learn a new thing, but in production, that is not good, and you will get more and more troubles if you want to fix errors/ add functionalities to the project later on.

For that reason, it’s important that after making the project functioning, every once and a while, we refactor our code in a understandable manner, so that other people, as well as our future selves, can understand. We will need a much larger series if we want to include this refactoring phase here, but if you could, please check out the final code, which I will link at the end of the article.

Some other ideas for improving the game

I hope that by now, you have gotten some ideas about how to make a game with pygame. We only have time to cover the basics, but here are some ideas that you may want to look at if you want to upgrade this game:

  1. Have some logic to store the scores (to a file, a database, etc.)
  2. Change game’s screen size (you can stack two background side-by-side and increase the number of pipes in pipe_system)
  3. Have more levels (increasing the difficulty by reducing GAP, reducing DISTANCE and widening the random range of top_pipe_length)
  4. Have pipes moving in up-down direction.

And of course, the sky is the limit for your creativity. This game is now yours, please feel free to do anything you want with it.

You can find the final version of the game in my Github repo

To see other posts in the same series, please click below:

Part 1 - Setup virtualenv

Part 2 - Setup Pygame

Part 3 - Start making game

Part 4 - Make a “flapping” flappy bird

Part 5 - Make the bird fly

Part 6 - Pipe System

Part 7 - Kill the Bird

Part 8 - Add game logic

Part 9 - Finalize the game

Written by Huy Mai