Create a Flappy Bird Clone With Python P2
Posted in tutorials python -This is one part of a multi-part tutorial. To see other posts in the same series, please click below:
Part 4 - Make a “flapping” flappy bird
PART 2: Install pygame
and start playing
At this point we are ready to start writing code. Let’s explore around to see what code to write. A quick Google search for “make game in python” shows that the most used library for making game in python is called Pygame.
With another search, I was able to find Pygame Documentation It seems to have several tutorials, which are likely to be useful to us as we write our own game.
The first step to do is to install pygame
using pip
:
pip install pygame
Surprisingly, and unfortunately, I got an error:
Collecting pygame
Using cached pygame-1.9.6.tar.gz (3.2 MB)
ERROR: Command errored out with exit status 1:
command: /home/dieu/Github/flappybird/venv/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-nxev5sni/pygame/setup.py'"'"'; __file__='"'"'/tmp/pip-install-nxev5sni/pygame/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-sek0qmaf
cwd: /tmp/pip-install-nxev5sni/pygame/
Complete output (18 lines):
WARNING, No "Setup" File Exists, Running "buildconfig/config.py"
Using UNIX configuration...
Hunting dependencies...
SDL : found 1.2.15
FONT : not found
IMAGE : not found
MIXER : not found
PNG : found
JPEG : found
SCRAP : found
PORTMIDI: found
PORTTIME: found
FREETYPE: found 23.1.17
Missing dependencies
----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
The error log looks quite complicated, and maybe even scary, but looks like there are some dependencies that are not available in the system. As I keep looking around, I found this page in Pygame Wiki, that explains how to build pygame
from scratch. While that might not be what we want, we might have to do it in the end, if nothing else works. However, this line in the instruction looks quite interesting to me:
#install dependencies
sudo apt-get install git python3-dev python3-setuptools python3-numpy python3-opengl \
libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl-ttf2.0-dev libsmpeg-dev \
libsdl1.2-dev libportmidi-dev libswscale-dev libavformat-dev libavcodec-dev \
libtiff5-dev libx11-6 libx11-dev fluid-soundfont-gm timgm6mb-soundfont \
xfonts-base xfonts-100dpi xfonts-75dpi xfonts-cyrillic fontconfig fonts-freefont-ttf libfreetype6-dev
As you see in the error log above, what I seemed to be missing were FONT
, IMAGE
and MIXER
, while among these packages we have libsdl-image1.2-dev
, libsdl-mixer1.2-dev
and libsdl-ttf2.0-dev
. My theory is that these packages are responsible for the dependencies that we are missing.
So I tried installing those packages with sudo apt-get install
and try pip install pygame
again. This time it works
Collecting pygame
Using cached pygame-1.9.6.tar.gz (3.2 MB)
Building wheels for collected packages: pygame
Building wheel for pygame (setup.py) ... done
Created wheel for pygame: filename=pygame-1.9.6-cp38-cp38-linux_x86_64.whl size=3832979 sha256=0eb9b839343f5c80db18d1823ab381a82171c0a95ba6ff3997ad6f0e57e7c4f2
Stored in directory: /home/dieu/.cache/pip/wheels/5c/3a/34/864e618a7e57b5df7cc5f1d1338aa43e7d566a4749a540c9b7
Successfully built pygame
Installing collected packages: pygame
Successfully installed pygame-1.9.6
These three missing packages only work in my case, since even if you are using Ubuntu like me, you may have missed other dependencies than I did. I just want to share the debugging process here for you to see things might get ugly from time to time, even for professional devs. In fact, a large part of your job as a software developer will be to debug those random errors.
If you run into the same situation like I did, the safest choice will be to install all packages listed in the
install dependencies
command.
There are actually simpler method to test if the library works listed in the Wiki, but I prefer to test it with a simple example, since that example might help us understand how pygame
works. Let’s try the bouncing ball tutorial in Pygame documentation to see if it works well.
Open VIM, or your favorite editor and create a file named intro.py
. Pasting the complete code in the tutorial to it:
import sys, pygame
pygame.init()
size = width, height = 320, 240
speed = [2, 2]
black = 0, 0, 0
screen = pygame.display.set_mode(size)
ball = pygame.image.load("intro_ball.gif")
ballrect = ball.get_rect()
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
ballrect = ballrect.move(speed)
if ballrect.left < 0 or ballrect.right > width:
speed[0] = -speed[0]
if ballrect.top < 0 or ballrect.bottom > height:
speed[1] = -speed[1]
screen.fill(black)
screen.blit(ball, ballrect)
pygame.display.flip()
Notice that we have the line pygame.image.load("intro_ball.gif")
, and there is an image of a ball there. When I right-clicked on the ball image and press “Save Image As…”, I could verify that the image’s name is, indeed, intro_ball.gif
. So I saved it to the project’s directory:
When we run python intro.py
, we can see that the ball is bouncing on a black screen, so pygame
works. Now press Ctrl-c
to stop it. Next, we would like to play around with these few lines of code to see what they do.
while 1:
is an infinite loop, so what’s running inside that block seems to be repeated infinitely. This is a normal way to make movements in games: by creating a sequence of still images, which “tricks” human brain into thinking that the image is actually “moving”. The movement is, however, so fast that it’s difficult to test this hypothesis. Let’s try adding some sleep
and print
lines:
import time
...
i = 0
while 1:
print(f"Frame {i}")
i += 1
time.sleep(1)
So basically, we set an one-second pause in every iteration, which, if the infinite loop is triggered as we predicted, should slow down the movement to 1 frame-per-second (fps). At the same time, in the terminal window that we run the command, an indicator of frame should be printed out.
And expected, that was what we get: as the ball slowly moves, we get the frame numbers display up in the terminal window.
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
Frame 0
Frame 1
Frame 2
Frame 3
Frame 4
Frame 5
Frame 6
Frame 7
Frame 8
The next step is to determine if we can change the speed of the ball. This speed
list looks like what we need to adjust. Right now it is [2,2]
, but let’s see how it goes if we change that. When we set it to [2, 0]
, the ball only moves horizontally, and with speed equals [0, 2]
the ball moves vertically. So we know that how the move
function works: it receives a list of length 2, whose first element changes the object’s horizontal and second changes its vertical position.
One thing that looks strange is the last line in the loop pygame.display.flip()
. We, luckily, have a search function in the Pygame Doc (Image)
Indeed, we had no problem getting the explanation:
pygame.display.flip()
Update the full display Surface to the screen
As an experiment, let’s try removing that line from the code. What we get is a black box with no ball.
The rest of the code looks quite easy to understand, so for every iteration:
- If the game receives
pygame.QUIT
event, it callssys.exit()
, which means quitting the program. - the
ballrect
object moves withspeed
, if it meets one of the screen edges, the ball’s speed changes to the opposite direction. screen.fill()
draws the frame’s background color.screen.blit()
draws the ball
So it seems that we have acquired quite a lot techniques to get closer to our Flappy Bird challenge. Let’s continue on the next post.
To see other posts in the same series, please click below: