Blake O'Hare .com

PyGame Tutorial Part 6 - More on Input

There are two basic ways to get the state of any input device. Those are checking the event queue or polling. Every time a key or button is pressed or released, or the mouse is moved, an event is added to the event queue. You must empty this event queue out each frame by either calling pygame.event.get() or pygame.event.pump().

pygame.event.get() will return a list of all the events since the last time you emptied the queue. The way to handle those events depends on the type of event itself. The type of the event can be checked by reading the event.type field. Examples of pretty much each type of common event can be seen in the extended code sample below. There are more types, but they are fairly uncommon.

The other way to check for events is to poll for the state of keys or buttons.

pygame.key.get_pressed() - will get a list of booleans that describes the state of each keyboard key. The value of the key constant (such as pygame.K_TAB) can be used as the index into this giant list. Therefore pygame.key.get_pressed()[pygame.K_TAB] is an expression that is true when the tab key is pressed.

pygame.mouse.get_pos() - returns the coordinates of the mouse cursor. Will return (0, 0) if the mouse hasn't moved over the screen yet.

pygame.mouse.get_pressed() - like pygame.key.get_pressed(), returns the state of each mouse button. The value returned is a tuple of size 3 that corresponds to the left, middle, and right buttons.

Here's a little program that has a bit of everything:

  • Moving the mouse causes a trail to be drawn after it.
  • Pressing W while holding Ctrl will close the window. Same for Alt + F4.
  • Pressing the close button will close the window
  • Pressing r, g, or b keys will make the trail turn red, green, and blue respectively.
  • Pressing the left mouse button will cause the trail to become thicker.
  • Pressing the right mouse button will cause the trail to become thinner.

import pygame

def main():
    screen = pygame.display.set_mode((640480))
    clock = pygame.time.Clock()
    radius = 15
    x = 0
    y = 0
    mode = 'blue'
    points = []
    while True:
        pressed = pygame.key.get_pressed()
        alt_held = pressed[pygame.K_LALT] or pressed[pygame.K_RALT]
        ctrl_held = pressed[pygame.K_LCTRL] or pressed[pygame.K_RCTRL]
        for event in pygame.event.get():
            # determin if X was clicked, or Ctrl+W or Alt+F4 was used
            if event.type == pygame.QUIT:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_w and ctrl_held:
                if event.key == pygame.K_F4 and alt_held:
                if event.key == pygame.K_ESCAPE:
                # determine if a letter key was pressed
                if event.key == pygame.K_r:
                    mode = 'red'
                elif event.key == pygame.K_g:
                    mode = 'green'
                elif event.key == pygame.K_b:
                    mode = 'blue'
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1# left click grows radius
                    radius = min(200, radius + 1)
                elif event.button == 3# right click shrinks radius
                    radius = max(1, radius - 1)
            if event.type == pygame.MOUSEMOTION:
                # if mouse moved, add point to list
                position = event.pos
                points = points + [position]
                points = points[-256:]
        # draw all points
        i = 0
        while i < len(points) - 1:
            drawLineBetween(screen, i, points[i], points[i + 1], radius, mode)
            i += 1

def drawLineBetween(screen, index, start, end, width, color_mode):
    c1 = max(0, min(2552 * index - 256))
    c2 = max(0, min(2552 * index))
    if color_mode == 'blue':
        color = (c1, c1, c2)
    elif color_mode == 'red':
        color = (c2, c1, c1)
    elif color_mode == 'green':
        color = (c1, c2, c1)
    dx = start[0] - end[0]
    dy = start[1] - end[1]
    iterations = max(abs(dx), abs(dy))
    for i in xrange(iterations):
        progress = 1.0 * i / iterations
        aprogress = 1 - progress
        x = aprogress * start[0] + progress * end[0]
        y = aprogress * start[1] + progress * end[1], color, (x, y), width)