PyGame

PyGame is a Python port of the SDL (Simple Directmedia Layer) Library. As the name suggests it's focus is writing games but is well suited to developing other types of applications and visualizations.

PyGame supplies the following:

... as well as many things I'm forgetting. I strongly recommend checking out their homepage when you get the chance.

An Example

Hello World (WITH BOXES!)

Because I know EXCITING, I thought I'd try showing you an "action packed" demo instead of the boring ol' hello world type stuff. First, a preview of what you're going to see produce:

bouncing boxes image
bounce.py: Initialization and Event handling

This first file is the main program. It is responsible for initializing PyGame and setting everything up for drawing.

/home/steder/Projects/Tutorials/python/BobChat-v0.3/BobClient.py
import time
import string
import random

# PyGame Constants
import pygame
from pygame.locals import *
from pygame.color import THECOLORS

import box

def main():
    WINSIZE = 640,480
    pygame.init()
    screen = pygame.display.set_mode(WINSIZE,0,8)
    pygame.display.set_caption('Bouncing Baby Boxes!')
    
    screen.fill(THECOLORS["black"])
    
    box1 = box.Box( screen, (32,32), (1,1), THECOLORS["black"], THECOLORS["white"] )
    box2 = box.Box( screen, (32,32), (-1,-1), THECOLORS["black"], THECOLORS["red"])
    box3 = box.Box( screen, (32,32), (1, 4), THECOLORS["black"], THECOLORS["green"])
    # The Main Event Loop
    done = False
    while not done:
        # Drawing:
        box1.draw()
        box2.draw()
        box3.draw()
        # Drawing finished this iteration?  Update the screen
        pygame.display.update()
            
        # Event Handling:
        events = pygame.event.get( )
        for e in events:
            if( e.type == QUIT ):
                done = True
                break
            elif (e.type == KEYDOWN):
                if( e.key == K_ESCAPE ):
                    done = True
                    break
                if( e.key == K_f ):
                    pygame.display.toggle_fullscreen()

    print "Exiting!"

    return
if __name__=="__main__":
    main()
    

Download bounce.py

box.py: Box Class w/ Drawing code

Box.py defines the Box class and it's draw method.

/home/steder/Projects/Tutorials/python/BobChat-v0.3/BobClient.py
import pygame
from pygame.locals import *

class Box:
    def __init__(self, screen, size, velocities, background, boxcolor):
        self.screen = screen
        screensize = self.screen.get_size()
        self.screenwidth = screensize[0]
        self.screenheight = screensize[1]
        # Position of Box on the Screen
        # Box will start roughly in the middle of the screen.
        self.x = screensize[0]/2
        self.y = screensize[1]/2
        self.width = size[0]
        self.height = size[1]
        # Velocity of the box
        self.vx = velocities[0]
        self.vy = velocities[1]
        self.bgcolor = background
        self.boxcolor = boxcolor
        self.rect = pygame.rect.Rect(self.x, self.y, self.width, self.height)

    def draw(self):
        # Erase the previous box
        pygame.draw.rect( self.screen, self.bgcolor, self.rect )
        # Update position or reverse direction
        # Check for collision with the sides:
        nx, ny = self.x + self.vx, self.y + self.vy
        bound_x = nx + self.width
        bound_y = ny + self.height
        if( (bound_x >= self.screenwidth) or
             (nx <= 0) ):
            self.vx *= -1 * 0.9 # Bounces decrease velocity slightly
        else:
            self.x = nx
        if( (bound_y >= self.screenheight) or
             (ny <= 0 ) ):
            self.vy *= -1 * 0.9
        else:
            self.y = ny
        # Draw the new box
        self.rect = pygame.rect.Rect(nx, ny, self.width, self.height)
        pygame.draw.rect( self.screen, self.boxcolor, self.rect )
        
        
    def setV(self,x,y):
        self.vx = x
        self.vy = y

    def setBackgroundColor(self, color):
        self.bgcolor=color
    def setBoxColor(self, color):
        self.boxcolor=color

Boxes consist of a screen height and width, a box height and width, a box velocity (as x and y components) in terms of standard python types. Boxes also include a Pygame Surface(called screen), 2 colors (background and box), and a Rect object. (Rect's represent drawable screen regions.)

The boxes are all moving, so when we draw a box, we first want to clear the rectangle on the screen where we used to be. So that is the first thing we do in the draw method. Next, we determine if we are near an edge or not. If the box has arrived at an edge we just reverse our velocity with respect to that edge. (If you hit the left or right sides you reverse self.vx, otherwise reverse self.vy.)

When our box is not bouncing, it's simply moving, so we just update it's coordinates by adding the velocity values to them(nx = self.x + self.vx). We then create a new Rect at our new coordinates and draw that rectangle to the screen.

Download box.py

More Examples

Heat

steady state heat visualization image

Heat is a visualization of a partial differential equation problem that I look at briefly in my Numeric Examples. Basically it is a color coded view of the field as it settles down

Life

game of life image

Life is an implementation of the Game of Life that automatically generates a large field of cells and lets it develop. This could easily be the beginnings of a screensaver or quickly adapted into a more traditional game of life (much smaller grid, place cells with your mouse, hit play and see if the colony lives or dies).

If you're not familiar with the Game of Life the concept is simple. Each green cell represents a living thing. Depending on the number of neighbors each cell has, it is either happy (and reproduces), average( it just sits there ), or depressed (it dies).

There is no traditional goal in this game. You don't really "win" or "lose". It's usually just interesting to see what sort of patterns come out of this simple algorithm.

The performance of this problem on this size grid is not nearly as good as I'd like but I haven't had sufficient time to optimize it. Perhaps optimization can be left to you as an exercise?

:~)