Published on (
 See this if you're having trouble printing code examples

Py Games

by Gareth Noyce

Computer games are big business. A team of 10 or 20 people may work feverishly behind closed doors for one to two years before the latest --insert game of your choice -- killer even sees the light of day. The average budget for this kind of development runs into hundreds of thousands of dollars, and that's before marketing gets involved! Given the risk and cost associated with game development, it's not surprising so many of today's games walk a fine line between derivative and evolutionary.

Large publishers are consolidating development houses or offering golden handcuffs to bring leading IP exclusively to a specific manufacturer's hardware. The barriers to entry into the games development industry are too large for just anyone to write a computer game.

Or are they?

The Tools Are Out There!

Ok, I'll come clean. The barriers to entry into the commercial games industry are high, probably too high. Bob and Joe aren't going to write the next killer Playstation 2 title just by sitting in their respective bedrooms for six months, beavering away in an effort to realize a good idea. But this doesn't mean all they can do is sit in the pub arguing over what would make a great game. Bob and Joe have advantages! They don't have margins or deadlines to worry about. They have a great idea, some free time and nothing to lose. Most importantly, Bob and Joe have free software and a network of people willing to share their knowledge in order to help them learn. Add to this an audience of people crying out for more games -- whatever the cost. There are powerful weapons in the budding game developer's armory.

Commercial-grade tools for the programmers, artists, and musicians amongst us are available at the price of a download. This helps us all in our daily lives, but it helps budding developers like Bob and Joe even more. They have at their disposal a choice of rock-solid operating systems to develop upon, and one of the cleanest, easiest-to-learn programming languages available: Python.

On The Shoulders of Giants

Language developers have made numerous attempts to create a language that's easy to learn, yet powerful enough for novice programmers to develop a game. Some, like Blitz Basic, have been moderately successful. Yet all these languages fall down in several areas:

Enter Pygame, stage left.

"What's Pygame?" I hear you mutter? Well, I'm glad you asked...

Pygame is a lightweight wrapper around the Simple DirectMedia Layer(SDL) -- stay with me here! -- a cross-platform library for accessing low-level graphics programming routines available under Windows, Linux, Mac OS, and BSD (amongst others). Think "DirectX" and you'd be close enough, except the beauty of SDL is it's free, non-proprietary, and extremely powerful.

Pygame provides an abstraction of SDL, giving you access to CD devices, keyboards and joysticks, fine-grained control of palettes and hardware-accelerated graphics primitives and, of course, the "mixer" module, allowing you to play anything from MP3s to WAV samples. Pygame contains everything you need to create a computer game.

But Why Py?

You might be wondering, "Is Python fast enough for game development?" Involved in a Pygame project since it's inception, I have been more than surprised at how fast Pygame can be. Sure, it's not C, but it's no slouch, either. Thanks largely to Pete Shinners and the dedicated and active development community that has sprung up around Pygame, it's only going to improve. There is a burgeoning library of contributed modules you can include in your own projects, a warm and friendly developers mailing list that's only too happy to help people with their problems, and of course the IRC channel (#Pygame on, where most of the "Pygame Projects" developers can be found. There's no problem that seems to go unanswered.

Game developers taking their first forays into "real" development come armed with a large collection of ideas, and a small bag of "clues" about how to realize them. It's demoralizing to get caught up in the intricacies of the chosen development language early in the project, or to realize that there is a large "tooling" time required to get a project off the ground. What these guys want is results! And quickly! The graphic artist wants to see if his character designs will work with his backgrounds, the sound guy wants to know if his music "feels" right, and the coder wants to know exactly how many screen updates (frames per second) he'll get shifting the proposed number of objects (sprites) around a certain-sized screen.

The beauty of Python and Pygame is they free developers from some of the more mundane chores that come with "lower level" languages such as C. You know the arguments: not having to worry about memory, no compile cycle, etc. etc. But it really does make a difference, when you consider the scope of computer games. The basics of Python syntax can be picked up in a couple of days, and the core Pygame functions in a couple more. It's not unfeasible for a novice game programmer to have a small test application up and running in less than a week! Don't believe me? Let's have a quick look.

We will create a simple framework for loading a sprite (a moveable image), set up a display, and blit (or copy -- this term is derived from "bit block transfer") the sprite onto our screen:

# Quick PyGame Example...
# Initialise SDL, display an image...

# For handling filenames...
import os

# The pygame module itself...
import pygame

# The image handling...
import pygame.image

# Important constant definitions for Pygame,
# in this example: used to setup the "Double
# Buffered" Display...
from pygame.locals import *

# Get the image from: ./images/sprite1.gif
sprite_file = os.path.join('images', 'sprite1.gif')

# Open up a display, draw our loaded image onto it
# -- check for ESC; if pressed, exit...
def main():
  # Initialise SDL environment

  # Setup a 640x480 screen...
  screen = pygame.display.set_mode((640,480), HWSURFACE|DOUBLEBUF)
  # Make a "surface" which is the same size as our screen...
  background = pygame.Surface(screen.get_size())

  # Make this background surface a white colour
  # (note: R,G,B tuple):

  # Load our sprite:
  sprite = pygame.image.load(sprite_file)
  # Get the initial position of the sprite,
  sprite_position = sprite.get_rect()

  # Set it's position to the middle of our display...
  sprite_position.bottom = (480 / 2)
  sprite_position.left = (640 / 2) - 100

  # Now "blit" the background and our sprite
  # onto the screen...
  screen.blit(background, (0,0))
  screen.blit(sprite, sprite_position)

  # Now display the screen buffer we've been
  # blitting things to...

  # Infinite loop to keep the window open until
  # ESC or "Close Window" widget
  # is pressed...
  while 1:
    # Get all "Events" that have occurred.
    # Check for keyboard input...
    keyinput = pygame.key.get_pressed()
    # If ESC or "QUIT" events occurred, exit...
    if keyinput[K_ESCAPE] or pygame.event.peek(QUIT):

# So we can run straight from the CLI...
if __name__ == '__main__':

A simple application that didn't involve the words "Hello World"! Save yourself some typing by downloading the examples. When executed, the example code looks something like this:

Screen shot.

We first set up a display 640 pixels wide by 480 pixels high. We've also opted for hardware acceleration (if available) and a "double buffered" display. (Double Buffering allows you to draw on a virtual display that is hidden from view until you switch or "flip" to it.)

Next we create a surface (think of it as a piece of clear plastic that you can draw on), that is the same dimension as our display, and we fill this with a white color -- this surface will act as our background.

We now load our sprite. Using the get_rect() method, we retrieve its current parameters. This allows us to set our sprite's position via the bottom and left attributes (and a few other useful things!). We can set these attributes to an integer value -- or use the existing values as the basis for dynamic modifiers.

With the sprite's position set (in the center of the display, in this example), we blit the background and the sprite to our screen buffer. Using pygame.display.flip(), we make our hidden buffer visible.

The example above is fairly simple, but it's trivial to extend this to move the sprite around our display. We already have an infinite loop that checks if the Escape key is being pressed; if we extend this to check for the cursor keys, we can modify the position of the sprite accordingly and display it in its new position, like so:

  while 1:
    # Get all "Events" that have occurred.
    # Check for keyboard input...
    keyinput = pygame.key.get_pressed()
    # If ESC or "QUIT" events ocurred, exit...
    if keyinput[K_ESCAPE] or pygame.event.peek(QUIT):

    # Ok, ESC not pressed, check for cursor keys...
    if keyinput[K_RIGHT]:
      sprite_position.left = sprite_position.left + 4

    if keyinput[K_LEFT]:
      sprite_position.left = sprite_position.left - 4
    if keyinput[K_UP]:
      sprite_position.bottom = sprite_position.bottom - 4    

    if keyinput[K_DOWN]:
      sprite_position.bottom = sprite_position.bottom + 4    

    # In case changes were made to the position,
    # redraw everything in it's new position...
    screen.blit(background, (0,0))
    screen.blit(sprite, sprite_position)


Voila! A moving sprite!

The example shown is very simple, but as you can see, Pygame handles complicated tasks with grace.

Things don't stop there! Python itself has many ways to impress. Need some networking for your game? No problem:

>>> import socket

Want to use an XML configuration file for the user parameters in the game? Great:

>>> import xml

Bob and Joe have the full power of Python and its standard modules at their disposal, power that removes the need for traditional proprietary formats or other custom developments normally associated with computer games.

In addition, Python provides a great platform for distributed games, as seen in early Ultima Online 2 developments. Python can also provide the means for players to customize ("mod") the game, something that's been popular since Doom hit the shelves. Customizing a game was recently taken to the extreme with "Severance, Blade of Darkness", which features an embedded Python interpreter within the game itself!

Related Reading

Programming Python, 2nd EditionProgramming Python, 2nd Edition
By Mark Lutz
Table of Contents
Sample Chapter
Full Description
Read Online -- Safari

Python and Pygame let developers concentrate on their ideas. You can quickly turn a discussion via email into working code, code that could end up in a final release with little or no change. Updates or modifications (with a bit of thought and the normal software engineering practices) are often trivial to do. It's an easy language for the novice to learn from other people's code, while being powerful enough to implement some extremely far-reaching ideas. Not to mention the fact that the combination of Python, Pygame, and SDL gives you real cross-platform development powers -- virtually the Holy Grail of the modern games industry.

What more could you ask for?

Infinite Lives

There are numerous examples of simple games that have taken a week to develop, as well as large projects that are still in development after a couple of years of work. Pygame has grown with them all, and continues to add new functions that will simplify the developer's life and provide new and interesting features. Python game development is easy and flexible.

With so few commercial developers free to take risks and bring revolutionary titles to market, maybe now is a perfect time to consider doing it yourself. It has never been easier to to sneak under their radar.

Gareth Noyce is an XML Architect by day and an independent Graphic Artist for Free Software projects by night.

Return to the Python DevCenter.

Copyright © 2009 O'Reilly Media, Inc.