Introduction to Pygame Zero¶
Creating a window¶
First, create an empty file called
Verify that this runs and creates a blank window by running
Everything in Pygame Zero is optional; a blank file is a valid Pygame Zero script!
You can quit the game by clicking on the window’s close button or by pressing
⌘-Q on Mac). If the game stops responding for any reason, you
may need to terminate it by pressing
Ctrl-C in your Terminal window.
Drawing a background¶
Next, let’s add a
draw() function. Pygame Zero will call this function
whenever it needs to paint the screen.
intro.py, add the following:
1 2 3 4 5
WIDTH = 300 HEIGHT = 300 def draw(): screen.fill((128, 0, 0))
pgzrun intro.py and the screen should now be a reddish square!
What is this code doing?
HEIGHT control the width and height of your window. The code
sets the window size to be 300 pixels in each dimension.
screen is a built-in that represents the window display. It has a
range of methods for drawing sprites and shapes. The
screen.fill() method call is filling the screen with a solid colour,
specified as a
(red, green, blue) colour tuple.
(128, 0, 0) will be a
Pygame Zero is actually calling your draw function many times a second. If your
draw() function draws slightly different things every frame, it will appear
as an animation. We’ll explore this shortly. For now, let’s set up a sprite
that we can animate.
Draw a sprite¶
Before we can draw anything, we’ll need to save an alien sprite to use. You can right click on this one and save it (“Save Image As...” or similar).
(This sprite has a transparency (or “alpha”) channel, which is great for games! But it’s designed for a dark background, so you may not be able to see the alien’s space helmet until it is shown in the game).
You need to save the file in the right place so that Pygame Zero can find it.
Create a directory called
images and save the image into it as
alien.png. Both of those must be lower case. Pygame Zero will complain
otherwise, to alert you to a potential cross-platform compatibility pitfall.
If you’ve done that, your project should look like this:
. ├── images/ │ └── alien.png └── intro.py
images/ is the standard directory that Pygame Zero will look in to find
There’s a built-in class called
Actor that you can use to represent a
graphic to be drawn to the screen.
Let’s define one now. Change the
intro.py file to read:
1 2 3 4 5 6 7 8 9
alien = Actor('alien') alien.pos = 100, 56 WIDTH = 500 HEIGHT = alien.height + 20 def draw(): screen.clear() alien.draw()
Your alien should now be appearing on screen! By passing the string
Actor class, it automatically loads the sprite, and has attributes
like positioning and dimensions. This allows us to set the
the window based on the height of the alien.
alien.draw() method draws the sprite to the screen at its current
Moving the alien¶
Let’s set the alien off-screen; change the
alien.pos line to read:
alien.topright = 0, 10
Note how you can assign to
topright to move the alien actor by its
top-right corner. If the right-hand edge of the alien is at
0, the the
alien is just offscreen to the left. Now let’s make it move. Add the following
code to the bottom of the file:
def update(): alien.left += 2 if alien.left > WIDTH: alien.right = 0
Pygame Zero will call your
update() function once every frame. Moving the
alien a small number of pixels every frame will cause it to slide across the
screen. Once it slides off the right-hand side of the screen, we reset it back
to the left.
Let’s make the game do something when you click on the alien. To do this we
need to define a function called
on_mouse_down(). Add this to the source
1 2 3 4 5
def on_mouse_down(pos): if alien.collidepoint(pos): print("Eek!") else: print("You missed me!")
You should run the game and try clicking on and off the alien.
Pygame Zero is smart about how it calls your functions. If you don’t define
your function to take a
pos parameter, Pygame Zero will call it without
a position. There’s also a
button parameter for
on_mouse_down. So we
could have written:
def on_mouse_down(): print("You clicked!")
def on_mouse_down(pos, button): if button == mouse.LEFT and alien.collidepoint(pos): print("Eek!")
Sounds and images¶
Now let’s make the alien appear hurt. Save these files:
- alien_hurt.png - save this as
- eep.wav - create a directory called
soundsand save this as
eep.wavin that directory.
Your project should now look like this:
1 2 3 4 5 6 7
. ├── images/ │ └── alien.png │ └── alien_hurt.png ├── sounds/ │ └── eep.wav └── intro.py
sounds/ is the standard directory that Pygame Zero will look in to find
your sound files.
Now let’s change the
on_mouse_down function to use these new resources:
def on_mouse_down(pos): if alien.collidepoint(pos): sounds.eep.play() alien.image = 'alien_hurt'
Now when you click on the alien, you should hear a sound, and the sprite will change to an unhappy alien.
There’s a bug in this game though; the alien doesn’t ever change back to a happy alien (but the sound will play on each click). Let’s fix this next.
If you’re familiar with Python outside of games programming, you might know the
time.sleep() method that inserts a delay. You might be tempted to write
code like this:
1 2 3 4 5 6
def on_mouse_down(pos): if alien.collidepoint(pos): sounds.eep.play() alien.image = 'alien_hurt' time.sleep(1) alien.image = 'alien'
Unfortunately, this is not at all suitable for use in a game.
blocks all activity; we want the game to go on running and animating. In fact
we need to return from
on_mouse_down, and let the game work out when to
reset the alien as part of its normal processing, all the while running your
This is not difficult with Pygame Zero, because it has a built-in
Clock that can schedule functions to be called later.
First, let’s “refactor” (ie. re-organise the code). We can create functions to set the alien as hurt and also to change it back to normal:
1 2 3 4 5 6 7 8 9 10 11 12
def on_mouse_down(pos): if alien.collidepoint(pos): set_alien_hurt() def set_alien_hurt(): alien.image = 'alien_hurt' sounds.eep.play() def set_alien_normal(): alien.image = 'alien'
This is not going to do anything different yet.
set_alien_normal() won’t be
called. But let’s change
set_alien_hurt() to use the clock, so that the
set_alien_normal() will be called a little while after.
def set_alien_hurt(): alien.image = 'alien_hurt' sounds.eep.play() clock.schedule_unique(set_alien_normal, 1.0)
clock.schedule_unique() will cause
set_alien_normal() to be called
schedule_unique() also prevents the same function
being scheduled more than once, such as if you click very rapidly.
Try it, and you’ll see the alien revert to normal after 1 second. Try clicking rapidly and verify that the alien doesn’t revert until 1 second after the last click.
We’ve seen how to load and draw sprites, play sounds, handle input events, and use the built-in clock.
You might like to expand the game to keep score, or make the alien move more erratically.
There are lots more features built in to make Pygame Zero easy to use. Check out the built in objects to learn how to use the rest of the API.