PyGame Guide/PyGame Crash Course

Your project folder and files
For the time being, we will store all of our source code in one .py file. Once your projects get larger, it is good to break out code into separate files, such as everything related to a given class in its own .py file.

When creating a new project in PyGame, all you need is one source file, but it is good to create a folder to contain the source code and all your images, fonts, and audio files in.

Usually, I'll create a folder named content or assets to store these multimedia files in, and keep the source code at the base level of my project folder. For example:


 * GAME FOLDER/
 * mygame.py
 * content/
 * graphics/
 * girl.png
 * gem.png
 * sounds/
 * hit.ogg
 * music.ogg

To access items within these paths, we use relative pathing. Anything in the base folder ("GAME FOLDER") is at the current directory, where your source file is. If you want to load an image, as part of the path you'd include the two folders within your "GAME FOLDER" base path.

Making a basic PyGame program
For a very basic PyGame program, we will at least need to do the following:


 * 1) Import the PyGame files
 * 2) Initialize the window
 * 3) Initialize the timer
 * 4) Create a game loop
 * 5) Check for input
 * 6) Update the game
 * 7) Draw to the screen
 * 8) Use the timer to regulate the framerate

We will cover loading files more in-depth later on, but for now let's look at the parts of my basic PyGame template. You can download the source code from |the repository, or follow along coding each little piece as I explain it.

Importing libraries
A library is code that has already been written ahead of time, and is packaged up so that it can be used in multiple programs. There are a lot of libraries for Python, and you can use multiple libraries at a time, but for now we just want the PyGame library.

To pull in another library in Python, we use the  command. PyGame has a bunch of functions we can use to load in graphics, handle program speed, detect input, and more. The  part contains shortcut named constants that are used as labels for event types, keyboard keys, and more. For now, you can take it for granted.

Initializing PyGame
To initialize PyGame, we need to use the following functions:

Here,  and   are variables. Variables are locations in memory where we can store data, and in this case the timer variable is an object that is responsible for making sure we have a constant frame-rate, and the window variable is where we will draw our text and graphics to. In Python, we don't need to declare variables before we use them (like we would in C++, Java, or C#). To create a variable, we just start using it. When we assign a value to the variable, it will figure out what the data type is on its own.

, , and   are all function calls. These are functions that are part of PyGame. Functions perform actions for us, though we don't need to know exactly how it works behind-the-scenes.

Within the parentheses of the functions we pass in arguments, which are essentially the inputs of the function. For example, in the set mode function, it takes in a  and   value, and it will set the screen to these dimensions. In this case, I've hard-coded it to 320 x 320 pixels.

The set caption function takes in a string, or a string of text. A string literal must be contained within double-quotes. This function sets the window's title bar text.

If you ran just the initialization code, a window would pop up and immediately close - that's because the program will read from top-to-bottom, and once it hits the bottom of the source file it will quit. This is where a game loop comes in.

The basic game loop
We want to make sure that the program keeps running until the user decides to quit. In order to do this, we can use a while loop.

Contents of a code block are indented

In Python, the contents of a function, if statement, or loop must be indented by one level. In C++, you might be used to these internal code-blocks being contained in curly braces {}, but this rule is different for Python.

As another example to illustrate t his:

Within the if statement, the print( “Inside the if statement” ) is indented forward by one level. Once the if statement is done, we indent backward once. This is required, as part of Python’s syntax.

Detecting a quit event
Since we are sitting inside of a while loop, each cycle something might happen. You might update your character to move forward by a few pixels, or a timer might go down, or the user might hit one or more keys.

In order to detect user input, we iterate through all of the events, which are captured by PyGame. If we detect a  event, we know the user wants to quit – they’ve hit the “X” button in the corner.

Updating the screen
At the end of the game loop cycle, we will want to update the screen so it will actually re-draw everything to the screen. We also want to regulate the framerate so that we stick to 30 or 60 frames per second, and the speed of the game doesn’t change from computer-to-computer.

First test
The code so far should look like this. Right now if you run it, the game window will just be a small black screen.

Once it runs, it will look like this:



Cleaning it up a little
It is good to organize your code, and periodically go back and refactor it to clean it up. If you never clean up your code, it will get messier and messier and messier, and be difficult to maintain or to keep adding on to it.

Additionally, it is better to use variables for data instead of hard-coding it in your function calls. This means you only have to update the data in one location (the variable assignment), and you won't have to go update a bunch of areas if you decide to change the data later on.

So, let's clean up the code above and add some variables to store information about the program.

Top of the program
Now if we need to know the dimensions of our game window, we simply need to use the  and   variables, instead of hard-coding 300 at every location.

Now we can change the initialization code to use these variables:

And at the end of the game loop, make sure to update the  function:

Creating color
Next, create a color so we aren’t just staring at a black empty window anymore. To create a color, we use the  class. The variable we store the data in then becomes an object-variable.

Within the parentheses, we’re passing in values for red, green, and blue. The color above will be a light blue. If you want to re-use the same color many times (for example, when drawing text), it is good to store the color in a variable so you can adjust the color in one place without updating it over and over everywhere in the code.

Within the game loop (right after while done is False:), add the following:

When you run the program, the game screen should be blue now.



Loading images
We can also load images and store these images in variables. Save the following two graphics to your Python project. Ideally, create a content folder and a graphics folder within it.





When you’re loading images, it should be outside of the game loop. Think of all of the code before the  as initialization code.

Load images:

And then draw them to the screen within the game loop with:

Second test
Here is the full code, though I have created a function called and put my init code within it.



Documentation links

 * pygame.time.Clock
 * 
 * pygame.display.set_mode
 * pygame.display.set_caption
 * pygame.display.update

Images
In the last example we loaded some images, but let’s look closer at these functions, and some other image-related functions that PyGame provides for us. To load an image into the program, you will use the pygame.image.load function.

Load an image
pygame.image.load


 * Inputs: filename (string)
 * Outputs: image surface object (store it in a variable)

When making a function call, any inputs go within the parentheses of the function. Since the input here is a string, the path to your image file should be contained within double-quotes like

"content/graphics/blorp.png"

And any outputs should be stored in a variable using an assignment statement.

The call to  will look like this:

Notes:

current path of the source code file you’re working in. For me, content is a folder at the same level as my .py file. Use forward-slashes, /, to differentiate between folders; the graphics folder is inside the content folder, and the grass.png image is within the graphics folder. load the image but you won’t be able to access it! Here, we are storing it in the variable imgGrass using the assignment operator, =. coding the path of an image to load, you need to make sure to write the path within double quotes. If text is not within double-quotes, Python will think that it is some sort of command or name, and it will give you errors.
 * The file path is relative - this means that it’s in relation to the
 * Store the result of the function in a variable - otherwise, it will
 * String-literals belong in double-quotes - when you’re hard-

Draw an image
pygame.Surface.blit


 * Inputs: source surface (pygame.image), destination rectangle (pygame.Rect)
 * Outputs: image surface object (store it in a variable)

Remember that we create a variable named :

The window variable is technically a  object. To draw our image to the screen, we use the  function, passing in the image variable and a rectangle, which contains the (x, y) coordinates, as well as width and height.

In this example, it hard-codes the position of the image to (320, 240). For movable characters, you will usually want to store their position and dimensions in a  variable so it can change during the game's run.

We can change the position at which an image is drawn by changing the rectangle input. If you want to be able to modify the position of your image while the program is running, it makes more sense to store this information in a variable.

During the game initialization, you could set up a rectangle like this:

And then update your  to use this rectangle variable:

Eventually, we will create a class for our characters, where their coordinates are stored as a variable, and we will use this for the draw function.

Draw part of an image


Sometimes you might want to draw only a portion of an image to the screen. Often, when working with animated sprites, all the sprites’ frames of animation are stored in one image file like this one.

To draw just a portion of the image at a time, we have to call the blit function with an extra argument:

Where in the SUB IMAGE RECT, you will specify the (x, y) of the pixel to begin at in the image, as well as the width and height of the region you want to draw.

So with this sprite sheet, if we wanted to draw the girl in row 3 and column 2, we would draw it like...

This will draw just the image on the spritesheet at the coordinate (1*frameWidth, 2*frameHeight), width the dimensions frameWidth x frameHeight.



Documentation links

 * pygame.Surface: https://www.pygame.org/docs/ref/surface.html
 * pygame.image: http://www.pygame.org/docs/ref/image.html
 * pygame.Rect: https://www.pygame.org/docs/ref/rect.html

Audio
In PyGame, we will treat sound effects and music a bit differently. Usually, you only have one background song playing at a time, while there might be multiple sound effects playing at once. For music you load in one music file at a time, while with sound files you store the sounds in variables to be played at any time.

Load a music file
pygame.mixer.music.load


 * Inputs: filename (string)
 * Outputs: none

Similarly to images, we can load in music files by passing in the path to your sound file. The path should be contained within double-quotes.

Play the music
pygame.mixer.music.play


 * Inputs: none
 * Outputs: none

Once a song has been loaded, we can then play it with this function.

Pause the music
pygame.mixer.music.pause


 * Inputs: none
 * Outputs: none

This will pause whatever music is currently playing on the channel.

Un-pause the music
pygame.mixer.music.unpause


 * Inputs: none
 * Outputs: none

Resume the music that is currently paused on the channel.

Set the music volume
pygame.mixer.music.set_volume


 * Inputs: volume (0.0 = none, 1.0 = full)
 * Outputs: none

This sets the volume that the music will play at. 0.5 is half-volume, 1.0 is full volume, and 0.0 is no volume.

Get the music volume
pygame.mixer.music.get_volume


 * Inputs: none
 * Outputs: volume (0.0 = none, 1.0 = full)

This will return the current volume the music channel is at

Create a sound file
pygame.mixer.Sound


 * Inputs: filename (string)
 * Outputs: Sound-object (store it in a variable)

We may have multiple sound effects we want to load into our game at any one time, so we will store each sound effect in a variable.

Play a sound file
pygame.mixer.Sound.play


 * Inputs: none
 * Outputs: none

This function must be called as part of a variable that stores a Sound object. When calling a function from the object, use the. operator.

Set the sound volume
pygame.mixer.Sound.set_volume


 * Inputs: volume (0.0 = none, 1.0 = full)
 * Outputs: none

This sets the volume that the music will play at. 0.5 is half-volume, 1.0 is full volume, and 0.0 is no volume.

Get the sound volume
pygame.mixer.Sound.get_volume


 * Inputs: none
 * Outputs: volume (0.0 = none, 1.0 = full)

This will return the volume that the one specific sound is set to.

Documentation links

 * pygame.mixer: https://www.pygame.org/docs/ref/mixer.html
 * pygame.mixer.music: https://www.pygame.org/docs/ref/music.html
 * pygame.mixer.Sound: http://www.pygame.org/docs/ref/mixer.html#pygame.mixer.Sound

Fonts and text
To draw text to the screen in PyGame, we must load in the font files that we are going to use. Then, using our font object, we can render text to an image Surface and draw it to the screen.

Loading a font
pygame.font.Font


 * Inputs: font path (string), font size (integer)
 * Outputs: none

Like with sound effects and images, to use fonts we want to create a Font object and store it in a variable. When creating the font, you need to pass in the font path, as well as the font size as input values.

Creating a text Surface
pygame.font.Font.render


 * Inputs: text (string), antialias (boolean), color (pygame.Color)
 * Outputs: text surface (store it in a variable)

When we want to turn the text into an image of text, we use the font object to render it to a surface.

Drawing a text Surface
pygame.Surface.blit


 * Inputs: source surface (pygame.image object), destination rectangle (pygame.Rect object)
 * Outputs: none

The draw functionality is part of the Surface object, but using the font we turned a text string into an image. You will need a window item created (See The bare-minimum PyGame program) to have something to draw the text to.

Documentation links

 * pygame.font: https://www.pygame.org/docs/ref/font.html
 * pygame.font.Font: https://www.pygame.org/docs/ref/font.html#pygame.font.Font

Keyboard and mouse input
As events occur in your game, Python will detect them and they will be stored and accessed via, which you can then iterate through and check what type of event it is. An event might be clicking the mouse button, or pressing down on a key on the keyboard, or even exiting the game. When the mouse is clicked, we can also get its (x, y) coordinates so that we can figure out what was being clicked - a button? A location to move to? And so on. You can also check for joystick/gamepad events, but we will just stick to keyboard and mouse for now.

Event types
Notice that with the events, there is a different for when you’re clicking down on the mouse button or on a keyboard key, and releasing it (or key-up). There might be multiple reasons for wanting to check for one or the other.

Once you’ve detected what kind of event is occurring, you can then get more information about what happened, such as which mouse button was clicked, or which key was pressed.

You can also use events like this to detect keyboard input, but this isn’t how you’ll want to get input for smooth character movement in your game. This would be more for small key presses. I’ll have more on how to get smooth keyboard movement later in this section.

Within the game loop, you will first need to check for events like this:

And then within the loop, you will use if statements to figure out (1) what kind of event happened, and (2) which button was pressed.

Mouse events
For mouse events, you have will start with the following.

Within the if statements is where you will look at which button was pressed and the mouse position.

gives you the mouse coordinates (x and y), and event.button gives you a number that represents which button was clicked.

With this code, the  statements will just write out text to the console, not the game itself, but you can use this for some light debugging or to experiment with at first.

The (x, y) coordinates also obey the rules of computer graphics, where the origin (0, 0) is at the top-left corner and increases right-ward and down-ward from there.

You can also check which button was pressed in the following way:

Keyboard events
You can detect keyboard input similarly to how you detect mouse input, but this isn’t the ideal way to get game input for smooth character movement. That part will be under the Smooth keyboard input section.

Detecting keyboard events in this way is fine for small keyboard features, maybe like typing in your name or hitting a keyboard shortcut, but if you’re going to have your character move around by holding down arrow keys, this is not the way to do it.

Once again, we start by iterating through the events, detecting whether we have a  or   event.

Then, if we have detected one of these events, we can then ask which key was pressed:

Smooth keyboard input
If your character is going to move by holding down a key on the keyboard, such as the arrow keys or WASD, you will want to use this technique instead. Instead of dealing with key presses as events, we use  pressed to see which keys are currently down.

Then, using the keycodes above, we can detect which keys are currently being held down. This will also work to check more than one key at once (like holding Run + Move).

Key codes
You can get a list of all the keycodes at https://www.pygame.org/docs/ref/key.html

Documentation links

 * pygame.event: http://www.pygame.org/docs/ref/event.html
 * pygame.key: https://www.pygame.org/docs/ref/key.html
 * pygame.mouse: https://www.pygame.org/docs/ref/mouse.html