Warning - This site is moving to https://getthecodingbug.anvil.app
Topics covered
Pygame recap
Creating basic game loop
How computers handle colour
Building a template
Input and Events
Pygame recap
Pygame is a “game library” - a set of tools to help programmers making games.
Some of the things it is used for are:
Graphics and animation
Sound (including music)
Control (keyboard, mouse, gamepad, etc.)
Game Loop
At the heart of every game is a loop, which we call the “Game Loop”.
This loop is constantly running, over and over again, doing all the things that are needed to make the game work.
Each time the game goes through this loop is called a frame.
During each frame, many different things may happen, but they can be organised into three different categories:
1. Process Input (or Events)
This means anything from outside your game that you want to pay attention to -
anything that you need the game to respond to.
These may be keys being pressed on the keyboard, the mouse being clicked, etc.
2. Update Game
This means changing anything that needs to change on this frame.
If a character is up in the air, gravity needs to pull it down.
If two objects run into each other, they need to explode.
3. Render (or Draw)
In this step, we draw everything on the screen.
Backgrounds, characters, menus, or anything else that the player needs to see must be drawn on the screen
in its correct, updated location.
Clock
One other important aspect of the loop is controlling how fast the whole loop runs.
You may have heard the term FPS, which stands for Frames Per Second.
This means how many times per second should this loop happen.
This is important because you don’t want your game to run too fast or too slow.
You also don’t want it to run at a different speed on different computers -
if your character should take 10 seconds to run across the screen,
that should be true no matter what computer it’s happening on.
How Computers handle Colour
We will be drawing shapes of different colours, so we need to define some constants for the colours.
Computer screens are made up of pixels, and these pixels have 3 parts to them: red, green, and blue. How much each part is lit up determines what colour that pixel is, like this:
Each of the three primary colours can have a value between 0 (off) and 255 (100% on), so there are 256 different possibilities for each of the three primary colours.
Here are some examples of some colours you can make:
# Define colours (R, G, B)
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
YELLOW = (255, 255, 0)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)
Our game will be made up of several files, and we may need to refer to these constants in more that one, so rather than defining them several times we will make a common file which we can import into several files.
Building a template
Now that we know what pieces we need to make the game work, we can start writing some code. To begin with, we’re going to make a simple pygame program that does nothing but open a window and run a game loop. This will be a great starting point for any pygame project you want to make.
Create a new folder called "Invaders".
Using the Python IDLE editor, create a New File and save it as "common.py" in the new folder "Invaders".
Place these lines in "common.py":
import pygame WIDTH = 800 # width of our game window HEIGHT = 600 # height of our game window FPS = 30 # frames per second # Define colours (R, G, B) BLACK = ( 0, 0, 0) WHITE = (255, 255, 255) YELLOW = (255, 255, 0) MAGENTA = (255, 0, 255) CYAN = ( 0, 255, 255) RED = (255, 0, 0) GREEN = ( 0, 255, 0) BLUE = ( 0, 0, 255)
Create another new file and save it as "main.py" in the new folder Invaders.
At the top of our program, we’re going to import our constants from "common.py" and any libraries we need:
# Pygame template - skeleton for a new pygame project from common import * import random
# initialize pygame and create window pygame.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("Your Game Title") clock = pygame.time.Clock()
Next we need to open the game window:
"pygame.init()" is the command to start up pygame and “initialise” it (which is a fancy word for start). screen will refer to our game screen, and we create it at the size we set in our configuration constants, in "common.py".
Finally, we create a clock so that we will be able to make sure our game runs at the FPS we want.
Now it’s time to make the game loop:
# Game Loop running = True while running: # Process input (events) # Update # Render (draw)
Here is our game loop, which is a while loop controlled by the variable "running". If we ever want the game to end, we just have to set "running" to "False" and the loop will end. Now we can fill in each of the sections with some basic code.
Render / Draw Section
We’ll start with the Draw section. We don’t have any characters yet, but we can fill the screen with a solid colour and then we can have our draw section fill the screen.
# Draw / render screen.fill(BLACK)
However, this isn’t quite enough, because of the way computer displays work. Changing a pixel on the screen means telling the video card to tell the monitor to change the actual pixel. In computer terms, this is a very, very slow process. So if you have a lot of things to draw on the screen, it can take a very long time to draw them all. We can fix this in a clever way by using something called double-buffering. This sounds fancy, but it really just means this:
Imagine we had one of those whiteboards that is 2-sided and can flip over to show one side or the other. The front will be the display (the screen the player sees), while the back is hidden and only the computer can “see” it. Every frame, we do all of our drawing on the back side - every character, every bullet, every sparkly light, etc. Then, when we’re done, we flip the board over and show the new frame. This means that we’re only doing that slow process of talking to the display once every frame, and not for every single thing on the screen.
All this happens automatically in pygame. You just have to tell it to flip that whiteboard when you’ve finished drawing. In fact, the command is even named flip():
# Draw / render screen.fill(BLACK) # *after* drawing everything, flip the display pygame.display.flip()
Just make sure that you always do flip() last. If you try to draw something after the flip, it won’t be seen!
Input / Events Section
We don’t have a game just yet, so we can’t really say what keys or mouse buttons or other controls we want to listen for. However, there’s one important event that we need to set up. If you tried running the program right now, you’d see that you have a problem: there’s no way to close the window! Clicking on the ‘X’ in the corner doesn’t work.
That’s because that’s actually an event, and we need to tell our program to listen for that event and have it exit the game.
Events can happen any time. What if the player clicks the ‘jump’ button while the update or draw part of the loop is happening? You don’t want to just ignore that input - the player will be frustrated. So what Pygame does is save up all the events that have happened since the last frame. That way if the player is quickly mashing lots of buttons, you can make sure you know about all of them. This will be a list, so we run a for loop to look at all of them. So under "# Process input (events)", add these lines:
for event in pygame.event.get(): # check for closing window if event.type == pygame.QUIT: running = False
Pygame has lots of events that it is able to look for. "pygame.QUIT" is the event that happens when the ‘X’ is clicked, so we set running to False and the game loop will end.
Controlling FPS
We don’t really have anything to put in the ‘Update’ section yet, but we do still need to make sure we use our FPS setting to control the speed. We can do that like this, add right under "while running":
while running: # keep loop running at the right speed clock.tick(FPS)
The "tick()" command tells pygame to figure out how long the loop took and then pause for however long it takes to make the whole loop (meaning the whole frame) to last the right amount of time. If we set FPS to 30, that means we want a frame to last 1/30 or 0.03 seconds. If our loop code (updating, drawing, etc) only takes 0.01 seconds, then pygame will wait for 0.02 seconds, for example.
Wrapping up
Finally, let’s make sure that when the game loop does end, we actually destroy the game window. We do this by putting pygame.quit() at the very end of our code. So our final pygame template looks like this:
can make, add these to your game, before the game loop:
# Pygame template - skeleton for a new pygame project from common import * import random # initialize pygame and create window pygame.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("Your Game Title") clock = pygame.time.Clock() # Game loop running = True while running: # keep loop running at the right speed clock.tick(FPS) # Process input (events) for event in pygame.event.get(): # check for closing window if event.type == pygame.QUIT: running = False # Update # Draw / render screen.fill(BLACK) # *after* drawing everything, flip the display pygame.display.flip() pygame.quit()
Congratulations! You should have a working Pygame template.
In the next section, we’ll use this template as the starting point for learning how to draw objects on the screen and make them move around. These objects are called "sprites".
Click this link to move on to the next section: Lesson 9 a