Before we begin looking seriously at the game of Pong itself, let’s first take a look at the overall general structure of a game program.
All games will generally have a form similar to that shown to the right.
In our initialisation routine, we set up the initial environment, get details for screen dimensions, input devices, audio, etc., then we enter the main Game Loop. This consists of a sequence of obtaining input from the user, updating the internal state of the program as a response to those inputs, then outputting the results to the screen. All of this has to occur within a split second (at a minimum we want to aim for 30 iterations per second) in order to give the illusion of smooth motion.
Layered on top of this overall flow, we also want our game to keep track of a number of possible states that it can be in. These correspond to the various modes.
For the purposes of our Pong implementation, we are going to want to have two possible states to begin with (which we may expand out later):
- Menu state: This will be the initial game state when we are waiting for a player to begin playing. It will also be the default state for the game when we first launch it. It will display some form of splash screen and instructions for the player to begin playing
- Game state: This will be entered from the menu state and will be the main gameplay controller. In this state, the player is actively playing against either another human being, or against the computer AI

From this, we can determine what Objects we are going to need to model within the game. At a first glance, we’re going to need the following:
- A paddle object. This will model the individual player’s paddle. There will need to be two instances of this during gameplay, one for player 1 and another for player 2. Rather than modelling the players as discrete objects, we’ll have the paddles act as a proxy for the player
- A ball object. This will model the ball itself and all its associated physics
- A game object. This will model the actual game and be responsible for keeping track of the individual scores and overall gamestate
- A menu object. This will be responsible for displaying the front-page menu and obtaining the requisite input from there to launch or exit the game
So, finally I’ll post up the minimum test program I’ve put together. This is intended as a simple test of the pygame framework to ensure it is installed and working correctly.
It doesn’t do anything particularly special, simply makes a full-screen, black window on the main display and sits there until the user presses the spacebar to terminate the execution. The display surface is 1024×768 and should be scaled to fit the existing desktop resolution
import pygame
class Main:
"""The main object used in the game"""
def __init__(self):
# Perform the basic initialisation and set up the screen
pygame.init()
resolution = (w, h) = (1024, 768)
display_flags = pygame.FULLSCREEN | pygame.SCALED
self.display_surface = pygame.display.set_mode(
resolution,
display_flags)
def run(self):
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
pygame.event.post(pygame.event.Event(pygame.QUIT))
if event.type == pygame.QUIT:
return
# End class Main
if __name__ == '__main__':
main = Main()
main.run()We can see from the above that I’ve defined the functionality as a Python class which is instantiated and executed from the guard block at the end of the file (lines 29-31).
Within the class, the __init__() method (which is called automatically by Python when the class is instantiated) performs the initial setup of the pygame environment and the display surface (which we save as an instance variable within the class so it can be referenced by our handler functions which we’ll add later).
The run() method forms the main program loop. All this does is execute indefinitely, checking the pygame event queue for the KEYDOWN and QUIT events. If a KEYDOWN event is detected, and the pressed key is the spacebar, then we pop a QUIT event onto the queue. When we read a QUIT event, the run() method returns and we terminate out of the main loop.
This basic framework will set us up nicely for the rest of the development. However, there is one thing that will need to be looked at before we can implement anything specific to our Pong game. Currently, the loop will execute as fast as the Python environment will let it. This means that any logic we add to the game will run quicker on faster, more powerful machines than on older machines. This is something we’ll need to address, so we may as well do so now, before we start adding too much complexity and game-specific code.
So, in the next post, we’ll take a look at options for throttling the loop and locking things to a predictable, manageable refresh interval.
The first step towards knowledge is to know that we are ignorant
Richard Cecil