(for CS5nm, P. Conrad, UCSB, 11/26/2008)
Before reading this, you should check out my article on PyGame drawing.
Lots of video games that you run on computers (as opposed to game consoles) use the keyboard—e.g. the arrow keys, or letters of the alphabet—to make things happen.
It is important to understand that when we press a key on the keyboard, there are two events:
In a game, we might want to allow the user to keep firing as long as the key is down, and then stop firing when the key comes back up, so we might want to handle these two events differently.
So, we need to distinguish between
So, again KEYDOWN means I pressed a key, and K_DOWN means the "down arrow" key.
For practice, answer these questions:
Answers:
Here's a PyGame program that lets you do something when you press a certain key.
We define functions for what should happen when each key is pressed—for example, there is a function handleDownKeyPressed() that is called when the down arrow is pressed (i.e. a KEYDOWN event on the K_DOWN key)
def handleDownKeyPressed(event): print "Yo, you pressed the down key"
In this example, that is a void function that just prints "Yo, you pressed the down arrow" on the console. Later, we'll see how we can make something more interesting happen. The parameter is a variable called event—as well see later, the event variable is often useful, even though here we aren't doing anything with it.
The code can be found here: keyboard1.py
In game programming, the idea of a "world" is useful concept. The world is a way of representing, in some compact way, the entire state of everything in the world of the game.
For example, consider a simple game where we have a spaceship that can move around the screen. The only thing that can change in the world from frame to frame is the position of that drawing. So, we can represent the entire state of the world with a single tuple, containing the x,y coordinates of that spaceship:
world = (100,200)
Later, if we have a more complicated world, with perhaps one friendly spaceship, and three enemy spaceships, we might represent the world with a list like this:
world = [ ('friend',100,200), ('enemy',150,200), ('enemy',130,120), ('enemy', 260,300)]
Or, if the spaceships all have some velocity, say a velocity in the horizontal (x) direction, and one in the vertical (y) direction, we might represent each spaceship with a tuple containing:
( kindOfSpaceship, xpos, ypos, xspeed, yspeed)
so we'd have, for example:
world = [ ('friend',100,200,4,5), ('enemy',150,200,2,3), ('enemy',130,120,-5,3), ('enemy', 260,300,4,-10)]
In any case, the idea is that we represent the entire state of the world with a single variable that is some kind of list of tuples, or a tuple of lists, or whatever. Then in each frame, the action of the game is simple:
In the next example, we'll see how this works—we'll go back to a simple world where the entire world is one spaceship.
Here's a simple pygame program that draws a spaceship. The spaceship is always at 100,100, which is the location represented by world. It is a pretty boring game, because nothing happens—the world never changes.
The spaceship code is pretty boring—just a triangle. You could probably draw a better one.
Here's the code: drawShip1.py
Now, we combine the two files together:
We make each of our functions that handles keyboard events take a world parameter, and return a new world parameter. This allows each of the keyboard events to "change the world".
If the world is different, then the picture we draw will be different.
Here's the combined file: keyboardShip1.py
In this file, the only events that change the world are pressing the down key, and pressing the up key:
def handleDownKeyPressed(event, world): return (world[0], world[1] + dy)
... def handleUpKeyPressed(event, world): return (world[0], world[1] - dy)
The other events take the world as it is and return the world, unchanged.
def handleDownKeyReleased(event, world): return world
So, if we want the other keys to do something, we just have to change those functions so that they also change the world.
Mouse events are handled in a similar way. Just like there are KEYDOWN and KEYUP events, there are also:
You can check the variable event.button to see which button was pressed—the value returned is an integer:
Here are two programs to illustrate this: