PyGame Basics

Let's get started

Introduction

In this section we will look at the basics of how PyGame works and get a basic implenentation working. It won't do too much at this stage but the next sections of the tutorial will build opon this to start making things interesting.

The template below is a good starting point for creating programs / games using PyGame. When creating a game, starting by copying in this code is a good way to begin.

The Template Code

The code below is a basic template for building a game in PyGame. There are other ways we could build this out but what we have below is a good simple starting point with the flexibility to do quite a lot.

Basic-Template.py

  1. import pygame, sys, random
  2. from pygame.locals import *
  3. pygame.init()
  4.  
  5. # Colours
  6. BACKGROUND = (255, 255, 255)
  7.  
  8. # Game Setup
  9. FPS = 60
  10. fpsClock = pygame.time.Clock()
  11. WINDOW_WIDTH = 400
  12. WINDOW_HEIGHT = 300
  13.  
  14. WINDOW = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
  15. pygame.display.set_caption('My Game!')
  16.  
  17. # The main function that controls the game
  18. def main () :
  19.   looping = True
  20.   
  21.   # The main game loop
  22.   while looping :
  23.     # Get inputs
  24.     for event in pygame.event.get() :
  25.       if event.type == QUIT :
  26.         pygame.quit()
  27.         sys.exit()
  28.     
  29.     # Processing
  30.     # This section will be built out later
  31.  
  32.     # Render elements of the game
  33.     WINDOW.fill(BACKGROUND)
  34.     pygame.display.update()
  35.     fpsClock.tick(FPS)
  36.  
  37. main()

Pygame template windowIf you put the above code into a file, save it and run it you should get a basic window open up similar to the one to the right.

Let's break this down and understand what's going on :

  • Lines 1 and 2 - import libraries that we are going to use. The Pygame library handles rendering all of our elements to the window. The sys library includes things for allowing our game to interface with the OS. The random library includes functions for generating random numbers (which we're not using yet but most games will want to so we may as well do it now and then we can forget about it).
  • Line 3 - asks PyGame to initialise itself. There's a bit that goes on here such as asking the OS for resources etc but for the most part we don't need to concern ourselves with what is going on.
  • Line 6 - creates a tuple of 3 integers which represent the amount of Red, Green and Blue. Their minimum value is 0 and maximum value is 255. We have put the variable name BACKGROUND in all caps to remind us that this is a variable which we are initialising at the top of the script and shouldn't change.
  • Line 9 - here we are creating a variable to dictate how many frames per second the game should run at.
  • Line 10 - we create a clock object which we can use later on to control the speed of our game.
  • Lines 11 and 12 - set up variables which will be used later on to create a window of these dimensions for the game.
  • Line 14 - asks PyGame to create a window of the given dimensions and assigns it to the variable WINDOW. Think of WINDOW as a handle which we can use later on to send things to the screen. (we could have just put the numbers for the window width and height straight in here and not worried about the variables but by using variables we can name what they represent which makes the code easier to follow.
  • Line 15 - sets the text which will show at the top of the window panel. You can actually call this function at any point during your game to change the text which is displayed there.
  • Line 24 - this line obtains all the current events since the last time we checked for events. Events are interractions such as keyboard presses and mouse movements. The QUIT event type is sent by the OS if, for instance, we click the close button on the window. This doesn't make the game quit, but gives the program an indication that it should. We can then do this on our own terms, eg. making sure that files with high scores etc are saved before quitting.
  • Lines 26 and 27 - tell PyGame to close down gracefully and then send a signal to the OS that it can close the program.
  • Line 30 - we're not doing anything here yet but we will be doing so over the next few pages of the tutorial.
  • Line 33 - sends a command to the WINDOW to paint the entire screen the given colour. If you don't do this then everything which is currently on the screen will stay there and new items will be placed over the top which most of the time is not what we want. (As your character moves, for instance they would leave a trail.)
  • Line 34 - takes all the commands which have been sent to the WINDOW and applies them to the actual screen in one go. This way you get a clean constant output rather than it being stuttery as different elements are rendered.
  • Line 35 - this command asks the system to pause for a brief while such that the game will run at the given Frames Per Second. If we didn't do this then the loop would run at a much faster cycle and potentially vary each time through the loop depending on what processing is going on. The end result would be erratic speed of your game which varied on each device depending on the devices hardware performance.
  • Line 37 we could have just put lines 19 - 35 not in a function and it would have worked pefectly fine but by putting it in a function like this we may create several similar functions to represent different screens in our game (home screen, settings, high scores, actual game, game levels etc). It also compartmentalises things which has several benefits which will become more apparent as we start to build up our games and the code becomes longer.

Building up the Template

This section is really just if you are interested but here I will build up the template piece by piece to see what effect the different sections have on your program. This can help you to understand what each sections is doing.

If you create a file and build it up following these code nippets it will help give you a better understanding of what each part of the code is doing.

The following code is the bare minimum required to get a window up and running :

Basic-Template.py

  1. import pygame, sys
  2. from pygame.locals import *
  3. pygame.init()
  4.  
  5. # Game Setup
  6. WINDOW_WIDTH = 400
  7. WINDOW_HEIGHT = 300
  8.  
  9. WINDOW = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))

You'll notice if you run it that the window pops up but then immediately disappears. This is because there is no game loop to keep the program running. Let's add that back in to keep the window open :

Basic-Template.py

  1. import pygame, sys
  2. from pygame.locals import *
  3. pygame.init()
  4.  
  5. # Game Setup
  6. WINDOW_WIDTH = 400
  7. WINDOW_HEIGHT = 300
  8.  
  9. WINDOW = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
  10.  
  11. # The main game loop
  12. while True :
  13.   filler = True #This is just so that the loop will actually run

Running the program now you will notice that the window stays open but if we try to close it by pressing the X button at the top nothing happens. That's because that button doesn't actually close the program. What it actually does is tell the OS (operating system) to send a message to the program that it should quit. The program can then do any tasks that it needs to do (eg. close files, check with the user about saving things etc) before actually quitting. We haven't got any code yet to close the program so let's put that in now.

Basic-Template.py

  1. import pygame, sys
  2. from pygame.locals import *
  3. pygame.init()
  4.  
  5. # Game Setup
  6. WINDOW_WIDTH = 400
  7. WINDOW_HEIGHT = 300
  8.  
  9. WINDOW = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
  10.  
  11. # The main game loop
  12. while True :
  13.     # Get inputs
  14.     for event in pygame.event.get() :
  15.       if event.type == QUIT :
  16.         pygame.quit()
  17.         sys.exit()

You'll notice that we've now taken out that temporary filler code on line 13 and replaced it with a for loop which allows us to grab all the events which have occurred since the last time through the loop and work through them one by one.

On line 15 we check if the event is of type QUIT and if it is then we shut down the program.

This for loop will be expanded in future parts of the tutorial with more if statements to allow you to detect other event types such as keyboard presses or mouse movements or presses.

Checking for events should always be the first thing we do in our game loop.

The last bit we will look at here is filling in the window with a background colour. Let's add in a variable to hold the background colour (because it's good programming practice to do this rather than just hard code the values).

Basic-Template.py

  1. import pygame, sys
  2. from pygame.locals import *
  3. pygame.init()
  4.  
  5. # Colours
  6. BACKGROUND = (255, 255, 255)
  7.  
  8. # Game Setup
  9. WINDOW_WIDTH = 400
  10. WINDOW_HEIGHT = 300
  11.  
  12. WINDOW = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
  13.  
  14. # The main game loop
  15. while True :
  16.     # Get inputs
  17.     for event in pygame.event.get() :
  18.       if event.type == QUIT :
  19.         pygame.quit()
  20.         sys.exit()
  21.  
  22.     # Render elements of the game
  23.     WINDOW.fill(BACKGROUND)

If you save and run this code you'll notice that nothing seems to change. The window is still black. That's because although we've put in the command to fill the window, rendering actions aren't applied straight away. They wait until we call the command to update the display. We always do this action as the last thing in our game loop so let's add that in now :

Basic-Template.py

  1. import pygame, sys
  2. from pygame.locals import *
  3. pygame.init()
  4.  
  5. # Colours
  6. BACKGROUND = (255, 255, 255)
  7.  
  8. # Game Setup
  9. WINDOW_WIDTH = 400
  10. WINDOW_HEIGHT = 300
  11.  
  12. WINDOW = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
  13.  
  14. # The main game loop
  15. while True :
  16.     # Get inputs
  17.     for event in pygame.event.get() :
  18.       if event.type == QUIT :
  19.         pygame.quit()
  20.         sys.exit()
  21.  
  22.     # Render elements of the game
  23.     WINDOW.fill(BACKGROUND)
  24.     pygame.display.update()

The reason for this behaviour is that it improves performance. Certain drawing actions may overlap on others. This means that each pixel will be updated only once rather than potentially multiple times. Asking the OS to draw to the screen is also quite a complex job so doing it only once saves resources and makes everything work that little bit quicker and smoother.

The remaining bits of the template will be expanded on in future parts of the tutorial so I won't discuss them now. Until we get more functionality in they won't have any noticeable impact on your program. They are in the template for convenience and will make it easier and quicker to get into doing the fun stuff later on.

The Game Loop

Programming languages like Python are what are known as procedural languages. The code is executed one line after the other starting at the top and working down to the bottom (with a few exceptions like loops and function calls adjusting the path here and there). When we get to the bottom the program is finished and it stops.

game loopA game however needs to continue running and continuously react to your inputs. We create a loop in our code to get it to keep running whilst we are playing the game. These loops are known as game loops and they typically take on a particular pattern which fits the way a game is structured.

Get inputs

At the beginning of the loop, identify all the interacctions which have occured (keyboard presses, mouse movements etc).

Process game elements

Here is where we put code to update the details of all the game elements. Move the enemies. Work out if health needs to change. Update the state of the character based upon any inputs that have happened. etc.

Render

Finally, draw everything to the screen in their updated states.

You don't have to do things in this order and we could in fact mix all the code for these three stages in together. For smaller, simpler games this may seem to be a quicker and easier approach. As your game gets bigger and more complex however it is going to be easier to manage if you break your code up into these three distinct sections.

Points to note

When building a PyGame program there are two points two things which commonly trip students up. They are easy to avoid though if you are aware of them.

1. Don't name your program pygame.py

If you name your program pygame.py then when you go to run it you will get an error stating that the pygame library can't be found. This is because of the way python works with respect to libraries. If you name your file as pygame.py then Python gets confused when you try to load the pygame library and things that your file is the library. It then tries to load PyGame from your file instead of the actual PyGame file.

This is really easy to avoid, just never name your file pygame.py.

2. Always include the code for getting events

This is lines 24 to 27 in the template above. Every time you create a new game loop (for different screens in your game, which you will learn about later) you will also need to include these lines as the first thing in your loop.

If you don't then your game will function fine at first but will soon become unresponsive.

The reason for this is that PyGame creates a queue for events which are passed to it by the OS (operating system). This queue builds up as the OS is constantly sending events (even though most of these events are not of interest to us they are still generated and added to the queue). Every time we call pygame.event.get() all the events currently in the queue are returned to us and the queue is cleared. If we don't call pygame.event.get() then the queue keeps growing and eventually overwhelms the computer (consuming too much memory).

So even if you don't need to react to any particular events in your game during a particular game loop, always include these lines of code anyway and you won't run into any issues. It will also mean that when you click the close button it will actually work.

Activities

Even though our program doesn't do too much just yet we can still tinker with a few elements to make sure we understand them.

Have a go at the following :

1. Change the numbers after the variable declarations for WINDOW_WIDTH and WINDOW_HEIGHT. What happens?

2. Can you change the dimensions of the game window to emulate a mobile phone screen?

3. Change the string 'My Game!' to something else. Save it and run your program again. Can you see what has changed?

4. Colours are created as a series of values representing the amount of Red, Green and Blue. 0 means none and 255 means full intensity. You can see above that we have full intensity for each of Red, Green and Blue and this sets the colour to white. If you tinker with those 3 values on the line setting the value for the variable BACKGROUND, changing the values to new values between 0 and 255 you can set the background to a heap of different colours.

If you set the values to (255, 0, 0) for instance, save and run your program you should see the background of the window change to red. See if you can find the combinations of values required to create the following colours :

  • Blue
  • Green
  • Light blue
  • Purple
  • Cyan
  • Yellow