Hi, I'm ThadeusB.

I code, I play, I love, I innovate

Pygame Event Input Wrapper

The goal of this class is to make input easier, and globally accessible to the entire game for each loop.

This also keeps track of whether an input has just been pressed, is being held down, and when it is released. Usage

Wrapper for the pygame input module

At the beginning of your loop where you would normally handle input put:

Input.add_events(pygame.event.get())

At the end of your loop you must add this so that events are transitioned correctly This makes sure events that are in a DOWN state get moved to a MOTION state (meaning they are being held down) and events in a UP state are removed from the dictionary.

Input.update()

Usage: To check a key use the pygame.locals. Such as K_a, K_d, K_ESC, etc. To check a mouse event use "MB1", "MB2", "MB3", etc. To check exit event use "QUIT" Support for up to 10 mouse buttons. Uses: Input[KEY] - Returns the pygame.event for KEY Input.isset(KEY) - True if there is an event for KEY Input.get(KEY) - Retrieve tuple of (pygame.event, status) Input.event(KEY) - Retrieve pygame event of key Input.stat(KEY) - Retrieve status value of key Input.down(KEY) - True if the key is a down event Input.motion(KEY) - True if the key is being held down Input.up(KEY) - True if the key is an up event

Download: Version 1

Input Wrapper (input.py) Input Wrapper Example (example.py) [brokenlink]

Alternatively you can get the latest version from my repository located at

hg clone http://hg.thadeusb.com/Games/MyRTS/

I will also try to keep the version located on the pygame cookbook updated to the latest version as well

http://www.pygame.org/wiki/InputWrapper?action=view

#Assume pygame is set up correctly
    while True:
        # yay for clocks.
        time_passed = clock.tick(MAX_FPS)
        # Update our mouse position and 3 button state
        Input.update_mouse(pygame.mouse.get_pressed(), pygame.mouse.get_pos())
        # Add all events from the event queue to the input module
        # for this loop cycle.
        Input.add_events(pygame.event.get())
        # Hopefully python's psuedocode nature explains what is going
        # on here.
        if Input.isset(K_q):
            print "Q IS SET"
        if Input.down(K_w):
            print "W WAS JUST PRESSED"
        if Input.motion(K_w):
            print "W IS BEING HELD DOWN"
        if Input.up(K_w):
            print "W WAS JUST RELEASED"
        if Input.down("MB1"):
            print "Mouse Button One Pressed"
        if Input.motion("MB1"):
            print "Mouse Button One Held Down"
        if Input.up("MB1"):
            print "Mouse Button One Released"
        # These will only be printed if the space bar
        # is currently in a event state.
        if Input.isset(K_SPACE):
            print "Event for MB2"
            print "Input['MB2']: ", Input["MB2"]
            print "Input.get('MB2'): ", Input.get("MB2")
            print "Input.event('MB2'): ", Input.event("MB2")
            print "Input.stat('MB2'): ", Input.stat("MB2")
        if Input.isset(K_END):
            exit()
        # To handle pygame.QUIT events. Such as user pressing X or Alt-F4
        if Input.isset("QUIT"):
            exit()
        # Update game objects and render them to the screen
        world.update(time_passed)
        world.render(screen)
        # This must be called at the end of each game cycle
        # This takes any event that was triggered this cycle as a
        # KEYDOWN or MOUSEBUTTONDOWN and moves them into a MOTION
        # state (meaning they are being held down).
        # This also takes any events received as a UP event and
        # removes them from the dictionary.
        Input.update()

        # Display our new screen.
        pygame.display.flip()

input_wrapper.py

#
# Wrapper for the pygame input module
#
# Copyright (C) 2009 Thadeus Burgess
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see /www.gnu.org/licenses/>

__author__="Thadeus Burgess <thadeusb@thadeusb.com>"
__date__ ="$Mar 23, 2009 12:20:34 AM$"

import pygame
from pygame.locals import *

class Input(object):
    """
    Wrapper for the pygame input module

    To check a key use the pygame.locals. Such as K_a, K_d, K_ESC, etc.
    To check a mouse event use "MB1", "MB2", "MB3", etc.
    To check exit event use "QUIT"

    Support for up to 10 mouse buttons.

    Uses:

    Input[KEY] - Returns the pygame.event for KEY
    Input.isset(KEY) - True if there is an event for KEY
    Input.get(KEY) - Retrieve tuple of (pygame.event, status)
    Input.event(KEY) - Retrieve pygame event of key
    Input.stat(KEY) - Retrieve status value of key
    Input.down(KEY) - True if the key is a down event
    Input.motion(KEY) - True if the key is being held down
    Input.up(KEY) - True if the key is an up event
    """
    DOWN = 1
    MOTION = 2
    UP = 3
    mice = (MOUSEBUTTONDOWN, MOUSEBUTTONUP, MOUSEMOTION)
    butt = {
            1: "MB1",
            2: "MB2",
            3: "MB3",
            4: "MB4",
            5: "MB5",
            6: "MB6",
            7: "MB7",
            8: "MB8",
            9: "MB9",
            10: "MB10",
    }
    events = {}

    button_state = ()
    mouse_pos = ()

    class __metaclass__(type):
        def __getitem__(cls, name):
            """
            Get the event.
            """
            try:
                event = Input.events[name][0]
            except KeyError:
                event = None

            return event

    @classmethod
    def add_event(cls, event):
        """
        Add a single pygame.event to the dictionary.
        """
        if event.type == KEYDOWN:
            Input.events.update({event.key: [event, Input.DOWN]})
        elif event.type == KEYUP:
            Input.events.update({event.key: [event, Input.UP]})
        elif event.type == MOUSEBUTTONDOWN:
            Input.events.update({Input.butt[event.button]: [event,Input.DOWN]})
        elif event.type == MOUSEBUTTONUP:
            Input.events.update({Input.butt[event.button]: [event,Input.UP]})
        elif event.type == MOUSEMOTION:
            Input.events.update({MOUSEMOTION: [event, Input.MOTION]})
        elif event.type == pygame.QUIT:
            Input.events.update({QUIT: [event, True]}) # Fix by Gautham(comment on the blog)

    @classmethod
    def add_events(cls, events):
        """
        Add a list of pygame.events to the dictionary
        Expects a pygame.event.get() as the argument.
        """
        for event in events:
            Input.add_event(event)

    @classmethod
    def get(cls, name):
        """
        Returns a list containing the pygame.event and a status code
        """
        try:
            event = Input.events[name]
        except KeyError:
            event = None
        return event

    @classmethod
    def event(cls, name):
        """
        Returns the pygame.event
        """
        event = Input.get(name)

        if event != None:
            event = event[0]

        return event

    @classmethod
    def stat(cls, name):
        """
        Returns the status code
        """
        event = Input.get(name)

        if event != None:
            status = event[1]
        else:
            status = None

        return status

    @classmethod
    def isset(cls, name):
        """
        Is there an event for name
        """
        try:
            # If this does not throw an exception
            Input.events[name]
            # We know the item exists
            event = True
        except KeyError:
            # Else it does not.
            event = False

        return event

    @classmethod
    def down(cls, name):
        """
        Is the event in a down state.
        Did the user press the key or button now
        """
        stat = Input.stat(name)

        if stat == Input.DOWN:
            return True
        else:
            return False

    @classmethod
    def motion(cls, name):
        """
        If the key is being held down.
        """
        stat = Input.stat(name)

        if stat == Input.MOTION:
            return True
        else:
            return False

    @classmethod
    def up(cls, name):
        """
        Has the key just been released
        """
        stat = Input.stat(name)

        if stat == Input.UP:
            return True
        else:
            return False

    @classmethod
    def update_mouse(cls, buttons = (0,0,0), pos = (0,0)):
        """
        Updates the mouse postion and the three main buttons state.
        pygame.mouse.get_pos() and pygame.mouse.get_pressed()
        """
        Input.mouse_pos = pos
        Input.button_state = buttons

    @classmethod
    def update(cls):
        """
        Updates the list to reflect the end of a game cycle.
        This way events that are in a down state get moved to
        a motion state (being held down) and events that are in
        a up state get removed from the list.
        """
        flag = []

        for i in Input.events:
            if Input.events[i][0].type == KEYDOWN:
                Input.events[i][1] = Input.MOTION
            elif Input.events[i][0].type == KEYUP:
                flag.append(i)
            elif i == MOUSEMOTION:
                flag.append(i)
            elif i in Input.butt.values():
                if i[:2] == "MB":
                    if Input.down(i):
                        Input.events[i][1] = Input.MOTION
                    if Input.up(i):
                        flag.append(i)

        for i in flag:
            del Input.events[i]

    @classmethod
    def tostring(cls):
        """
        Print the list of events.
        """
        #for i in Input.events:
            #print Input.events[i]
        if len(Input.events) > 0:
            print Input.events