PyGame Drawing Basics

Getting Started

You must do the following to get started with Pygame:

import pygame
import sys


pygame.init()

Strictly speaking, import sys is not needed for PyGame, but as we'll see later, to be able to use the "close window" button on Windows or Mac, we'll need to use sys.exit(), so it is helpful.

Opening a Window

To open a window of size 640,480, use the statement below.

screen = pygame.display.set_mode((640,480))

The screen

If your screen is of size 640,480:

Updating the Screen

Changes you make to the screen—e.g. filling it with color, or drawing on it—do not show up immediately!

Instead, you have to call this function

pygame.display.update()

Why do you have to do this?

Colors

colorName = (r,g,b)

Examples:

red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
darkBlue = (0,0,128)
white = (255,255,255)
black = (0,0,0)
pink = (255,200,200)

Drawing

Remember that after you draw, you have to call pygame.display.update() before your changes show up.

screen.fill(color)
pygame.draw.lines(screen, color, closed, pointlist, thickness)

pygame.draw.rect(screen, color, (x,y,width,height), thickness)
pygame.draw.circle(screen, color, (x,y), radius, thickness)
pygame.draw.arc(screen, color, (x,y,width,height), start_angle, stop_angle, thickness)

Writing your own drawing functions

You can use functions to help you draw in PyGame in two different ways:

Specialized Drawing Functions (as in ex06)

The first way is illustrated below. This function actually draws a house. First it forms a list of points, and then it uses them to draw the house by calling pygame.draw.lines()

def drawHouse(x, y, width, height, screen, color):
    points = [(x,y- ((2/3.0) * height)), (x,y), (x+width,y), (x+width,y-(2/3.0) * height), 
        (x,y- ((2/3.0) * height)), (x + width/2.0,y-height), (x+width,y-(2/3.0)*height)]
    lineThickness = 2
    pygame.draw.lines(screen, color, False, points, lineThickness)

Functions that return lists of points (as in ex09)

The second way is illustrated below. First, we have a function that creates the list of points:

def makeHouseFrame(x,y,width,height):
   points = [] # start with an empty list
   points.append((x,y- ((2/3.0) * height))) # top of 1st story, upper left
   points.append((x,y))  # lower left corner
   points.append((x+width,y)) # lower right corner
   points.append((x+width,y-(2/3.0) * height)) # top of 1st story upper right
   points.append((x,y- ((2/3.0) * height))) # top of first story, upper left
   points.append((x + width/2.0,y-height)) # top of roof
   points.append((x+width,y-(2/3.0)*height)) # top of 1st story, upper right
   return points

Then, we can just use those points to draw a house like this.

def drawHouse(x,y,width,height,screen,color):
   lineThickness = 2 
   pygame.draw.lines(screen, color, False,
           makeHouseFrame(x,y,height,width), lineThickness)

Note that we have a function call to makeHouseFrame() as the fourth argument to the pygame.draw.lines() function call.

Comparing the two techniques

At first, it may seem like this is not progress. We've turned a simple five line function into two functions, and fourteen lines of code—that do the very same thing.T

This seems to go against the idea that "simple is better than complex".

However, the second version has several advantages:

Restructuring our code like this is an example of "refactoring" (discussed in section 4.7 of the textbook)

Enabling the quit button (red X on Windows, red circle on Mac)

To make the quit button work, we need two things:

  1. An infinite loop, that goes around and around looking for events
  2. Some code that looks for a QUIT event, and handles that event

The infinite loop part is easy. Here is an infinite loop in Python:

while (True):
    # do something

Whatever we have in place of # do something will be done over and over again, until we exit the program.

What is it that we want to do over and over? Each time through the loop, we need to look for quit events and if we find one, we need to quit the program:

   for event in pygame.event.get():
        if event.type == pygame.QUIT:
             pygame.quit(); sys.exit();

This code says the following:

We put this code inside a while (True): infinite loop so that we can do it over and over again—we have to keep doing it, because we don't know when the user will click the red X.

Animation (making drawings move)

To make a drawing move, you just put code inside your infinite loop that

Remember:

So you have something like this:

while (True):

# check for quit events
for event in pygame.event.get():        if event.type == pygame.QUIT:             pygame.quit(); sys.exit();

# erase the screen
screen.fill(white)

# draw the updated picture

updatePoints(points) # changes the location of the points
pygame.draw.lines(screen,black,false,points,1) # redraw the points # update the screen
pygame.display.update()

Making the motion go faster or slower

There are at least two ways to make the motion go faster or slower

One simple way to slow things down is to insert a call to pygame.time.delay(5) somewhere inside the loop—the number is the number of milliseconds to delay.

A better way is to use a clock.

To use a clock:

  1. Put the code clock = pygame.time.Clock() near the start of the program, somewhere after pygame.init() but definitely outside the main loop
  2. Inside the loop, put the code msElapsed = clock.tick(30) where 30 is the frame rate you want (e.g. 30 frames per second)

Smoother Motion

If you want to get really fancy, and make your motion as smooth an as accurate as possible, you can check the value of msElapsed, which will tell you how much time elapsed since the last call to clock.tick(30).

In theory, it should be close to 1000.0/30.0 milliseconds. In practice it might be more or less, depending on the load on your machine.

You can use to value of msElapsed to determine how far to move your drawing.


References:

P. Conrad, UC Santa Barbara.

(end of document Pygame Drawing Basics)