> Pygame: Keyboard Input Detection

One type of event that can be checked for while inside our game loop is keyboard inputs. A keyboard input event will be detected using the pg.event.get() method (assuming we had used import pygame as pg so that we don't have to fully type out "pygame" in all of our pygame methods).

Note: The following code is not actual code from the Frogger game example; some code was taken out to avoid confusion and streamline your understanding of keyboard input detection.


running = True
while running:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            running = False
        if event.type == pg.KEYDOWN:
            if event.key == pg.K_UP:
                frog.move_frog("UP")
            elif event.key == pg.K_DOWN:
                frog.move_frog("DOWN")
            elif event.key == pg.K_LEFT:
                frog.move_frog("LEFT")
            elif event.key == pg.K_RIGHT:
                frog.move_frog("RIGHT")
        

Above is an example of the game loop parsing different pygame events. In the code for TicTacToe, we only say events that dealt with quitting and mousedown. Now we are looking at the KEYDOWN event type in main.py. Notice that we are using a for loop to detect events, meaning that pg.event.get() must return an iterable. We can think of this returned iterable as a constantly-changing list of events, ordered by which event occured first, like a queue. It is constantly changing because events are always being added as we do certain things like click the screen, press keys, or quit the game.

These events are actually objects from an Event class that is built into the pygame library. Instances of this underlying Event class contain information about the event itself. It makes sense that these are actually objects because the script variable event (which represents an Event object) has attributes that we retrieve using dot notation.


if event.type == pg.KEYDOWN:
    

event.type will tell us whether the event is a key press (pg.KEYDOWN), mouse click (pg.MOUSEBUTTONDOWN), quitting the window (pg.QUIT), etc. If the event type is indeed keyboard input, the other event attribute we will care about is event.key, which will tell us exactly which key was pressed.


if event.key == pg.K_UP:
    

pg.K_UP is just pygame's way of representing the up arrow key. Notice that we have conditionals to catch all arrow key presses.


if event.key == pg.K_UP: # Up Arrow Key
    frog.move_frog("UP")
elif event.key == pg.K_DOWN: # Down Arrow Key
    frog.move_frog("DOWN")
elif event.key == pg.K_LEFT: # Left Arrow Key
    frog.move_frog("LEFT")
elif event.key == pg.K_RIGHT: # Right Arrow Key
    frog.move_frog("RIGHT")
    

You are not limited to arrow key presses; check out the pygame documentation on key presses to see all of the key presses that you can detect: pygame.key.

Now that we have conditionals to catch all kinds of key presses, we can control what the game does in response to user keyboard input. You will notice that we have a call to frog.move_frog with every arrow key press we detect The move_frog function is a method bound to the Frog class that changes the rect.x, rect.y, and lane instance attributes of our frog instance, effectively moving the frog object itself. This is because our Frog class inherits from the pg.sprite.Sprite class, which uses rectangles to represent size and location. Rectangles in pygame have x and y attributes. When we draw a rectangle, or a Sprite that has a rect attribute, we use the x and y values of the rectangle to tell us where to draw. Over many iterations of the game loop, the drawing of a Sprite at different x,y coordinates will simulate movement.


def move_frog(self, direction):
    if (self.lane == 0 and direction == "DOWN") or # Checks if move is out of (bottom) bounds
        (direction == "LEFT" and self.rect.x - self.block_size < 0) or # Checks if move is out of (left) bounds 
        (direction == "RIGHT" and self.rect.x + self.width >= screen_width): # Checks if move is out of (right) bounds
        return None
    elif direction == "UP": # Move frog up
        self.lane += 1
        self.move_y -= self.block_size
    elif direction == "DOWN": # Move frog down
        self.lane -= 1
        self.move_y += self.block_size
    elif direction == "LEFT": # Move frog to the left
        self.move_x -= self.block_size
    elif direction == "RIGHT": # Move frog to the right
        self.move_x += self.block_size
    

Similar to the move function in the Obstacles class, the move function in the Frog class only changes the attributes self.move_x and self.move_y. the update function for the frog class will change the actual coordinates.

Moving some object does not have to be the only thing that happens upon key presses. With the functionality of our game loops and keyboard input detection, we can make anything happen upon certain events; we are not limited to checking for arrow key presses and only moving objects around.