PyGameExamplesAndAnswers

StackOverflow            reply.it reply.it

“You should name a variable using the same care with which you name a first-born child.”
Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship


Keys and keyboard events

Related Stack Overflow questions:

When does it make sense to use keyboard events (pygame.KEYDOWN, pygame.KEYUP see pygame.event), and when is it better to get the state of the keys (pygame.key.get_pressed())?

pygame.key.get_pressed() returns a sequence with the state of each key. If a key is held down, the state for the key is 1, otherwise 0. It is a snapshot of the keys at that very moment The new state of the keys must be retrieved continuously in each frame. So you can calculate the resulting movement when 2 keys are pressed with keys[pygame.K_d] - keys[pygame.K_a] and keys[pygame.K_s] - keys[pygame.K_w]. Use pygame.key.get_pressed() to evaluate the current state of a button and get continuous movement.

while True:

    keys = pygame.key.get_pressed()
    x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * speed
    y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * speed

The keyboard events (see pygame.event module) occur only once when the state of a key changes. The KEYDOWN event occurs once every time a key is pressed. KEYUP occurs once every time a key is released. Use the keyboard events for a single action like jumping or spawning a bullet or a step-by-step movement.

Single Action:

while run:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                fire_bullet()

Step-by-step movement:

while run:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                x -= speed
            if event.key == pygame.K_RIGHT:
                x += speed
            if event.key == pygame.K_UP:
                y -= speed
            if event.key == pygame.K_DOWN:
                y += speed

Shoot bullet

Related Stack Overflow questions:

The general approach to firing bullets is to store the positions of the bullets in a list (bullet_list). When a bullet is fired, add the bullet’s starting position ([start_x, start_y]) to the list. The starting position is the position of the object (player or enemy) that fires the bullet. Use a for-loop to iterate through all the bullets in the list. Move position of each individual bullet in the loop. Remove a bullet from the list that leaves the screen (bullet_list.remove(bullet_pos)). For this reason, a copy of the list (bullet_list[:]) must be run through (see How to remove items from a list while iterating?). Use another ` for-loop to blit` the remaining bullets on the screen:

bullet_list = []

while run == True:
    # [...]

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                bullet_list.append([start_x, start_y])

    for bullet_pos in bullet_list[:]:
        bullet_pos[0] += move_bullet_x
        bullet_pos[1] += move_bullet_y
        if not screen.get_rect().colliderect(bullet_image.get_rect(center = bullet_pos))
            bullet_list.remove(bullet_pos)

    # [...]

    for bullet_pos in bullet_list[:]
        screen.blit(bullet_image, bullet_image.get_rect(center = bullet_pos))

    # [...]

Key state

What does pygame.key.get_pressed() do?

Related Stack Overflow questions:

Key repeat

Related Stack Overflow questions:

Keyboard event

What is pygame.KEYDOWN, pygame.KEYUP?

Related Stack Overflow questions:

The keyboard events KEYDOWN and KEYUP (see pygame.event module) create a pygame.event.Event object with additional attributes. The key that was pressed can be obtained from the key attribute (e.g. K_RETURN , K_a) and the mod attribute contains a bitset with additional modifiers (e.g. KMOD_LSHIFT). The unicode attribute provides the Unicode representation of the keyboard input.
pygame.key.get_pressed() returns a list with the state of all keyboard buttons. This is not intended to get the key of a keyboard event. The key that was pressed can be obtained from the key attribute of the pygame.event.Event object:

if event.type == pg.KEYDOWN:
    if event.key == pg.K_a:
        # [...]

unicode contains a single character string that is the fully translated character:

if event.type == pg.KEYDOWN:
    if event.unicode == 'a':
        # [...]

See also pygame.event module and pygame.key.

If you press UP + LEFT + SPACE then the SPACE key doesn’t appear to be pressed immediately. You’ve to release the UP or LEFT key to get the pygame.KEYDOWN event for SPACE.

This is a known bug in pygame and doesn’t seem to be solved yet: Incorrect handling of pressed keys #235.

Sadly even pygame.key.get_pressed() doesn’t state the SPACE key in this case, so I can’t even think a workaround.

While pygame.K_f is a key enumerator constant (see pygame.key) the content of event.type is event enumerator constant (see pygame.event).
If you want to determine if a certain key is pressed, the you’ve to verify if the event type is pygame.KEYDOWN (or pygame.KEYUP for button release) and if the .key attribute of the event is equal the key enumerator. e.g.:

for event in pygame.event.get():
    if event.type == pygame.QUIT:
        self.quit()

    # [...]

    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_f:
            # [...]

Key representation

Related Stack Overflow questions:

A user friendly name of a key can be get by pygame.key.name():

for event in pygame.event.get():
    if event.type == pygame.KEYDOWN:

        print(pygame.key.name(event.key))