Search code examples
pythonpygamekeyrepeatkeyboard-events

Key to be pressed multiple times to move image in pygame


While I was learning how to move images in pygame, when I held down a key(any one: up, down, left, right) to move my image(a racecar), the image only moved once, even though holding down the key should've made the image move move in that particular directions continuously, but it only moved one unit. The fix that I found was that the declaration of the variables used to change the original position (x_vary and y_vary, original position: x and y) were not be added in the main while loop of my game.

My question is why? Why does it make a difference where I declare x_vary and y_vary

Here is the unfixed code:

import pygame

pygame.init()

clock = pygame.time.Clock()

game_window = pygame.display.set_mode((800, 600))
game_icon = pygame.image.load('icon2.jpg')
game_caption = pygame.display.set_caption('Racecar Game')

x = 800 * 0.45
y = 600 * 0.08

racecar = pygame.image.load('racecar.png')

def car(x, y):
    game_window.blit(racecar,(x,y)) 

game_run = False

while game_run == False:

    x_vary = 0
    y_vary = 0

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            game_run = True
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                x_vary = -10
            elif event.key == pygame.K_RIGHT:
                x_vary = +10
            elif event.key == pygame.K_UP:
                y_vary = -10
            elif event.key == pygame.K_DOWN:
                y_vary = +10
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                x_vary = 0
                y_vary = 0

    x += x_vary
    y += y_vary

    game_window.fill((128, 0, 0))
    car(x, y)

    pygame.display.update()
    clock.tick(60)

pygame.quit()
quit()

Solution

  • The keyboard events (pygame.KEYDOWN, pygame.KEYUP) occur only one time when a key is pressed, respectively released.

    If x_vary = 0 and y_vary = 0 are declared in the main application loop, then they are set when a button is pressed, but they are reinitialized (0) immediately in the next frame. You've to presse a button again to set them.

    If x_vary = 0 and y_vary = 0 are declared before the main application loop, then they keep the value, which is set when a button is pressed. If a button is released, then both are set 0.

    Use pygame.key.get_pressed(), to evaluate if the state of a key is pressed. pygame.key.get_pressed() get the state of all keyboard buttons and a the state of a key is True as long the keyboard is pressed down. e.g.:

    game_run = False
    while game_run == False:
    
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_run = True
    
        keys = pygame.key.get_pressed()
        x_vary, y_vary = 0, 0
        if keys[pygame.K_LEFT]:
            x_vary = -10
        if keys[pygame.K_RIGHT]:
            x_vary = +10
        if keys[pygame.K_UP]:
            y_vary = -10
        if keys[pygame.K_DOWN]:
            y_vary = +10
    
        x += x_vary
        y += y_vary
    
        game_window.fill((128, 0, 0))
        car(x, y)
    
        pygame.display.update()
        clock.tick(60)