How can I make a sprite move when key is held down

Posted on

Problem :

Currently the sprite only moves 1 pixel every time a key is pressed. How could I cause the plumber sprite to move constantly when left or right key is being held down?

while running:
    setup_background()
    spriteimg = plumberright

    screen.blit(spriteimg,(x1, y1))

    for event in pygame.event.get():
         if event.type == pygame.QUIT:
             running = False
         elif event.type == pygame.KEYDOWN:
             if event.key == pygame.K_UP:
                 x1 = x1 + 0
                 y1 = y1 - 1
             elif event.key == pygame.K_DOWN:
                 x1 = x1 + 0
                 y1 = y1 + 1
             elif event.key == pygame.K_LEFT:
                 x1 = x1 -1
                 y1 = y1 + 0
             elif event.key == pygame.K_RIGHT:
                 x1 = x1 + 1
                 y1 = y1 + 0

    pygame.display.flip()
    clock.tick(120)

Solution :

You can use pygame.key.get_pressed to do that.

example:

while running:
    keys = pygame.key.get_pressed()  #checking pressed keys
    if keys[pygame.K_UP]:
        y1 -= 1
    if keys[pygame.K_DOWN]:
        y1 += 1

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 or a step-by-step movement.

If you want to achieve a continuously movement, you have to use pygame.key.get_pressed(). pygame.key.get_pressed() returns a list with the state of each key. If a key is held down, the state for the key is True, otherwise False. Use pygame.key.get_pressed() to evaluate the current state of a button and get continuous movement:

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

    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        x1 -= 1
    if keys[pygame.K_RIGHT]:
        x1 += 1
    if keys[pygame.K_UP]:
        y1 -= 1
    if keys[pygame.K_DOWN]:
        y1 += 1

    setup_background()
    spriteimg = plumberright
    screen.blit(spriteimg, (x1, y1))

    pygame.display.flip()
    clock.tick(100)

See also Key and Keyboard event

Minimal example: repl.it/@Rabbid76/PyGame-ContinuousMovement

import pygame

pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()

rect = pygame.Rect(0, 0, 20, 20)
rect.center = window.get_rect().center
vel = 5

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.KEYDOWN:
            print(pygame.key.name(event.key))

    keys = pygame.key.get_pressed()
    
    rect.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * vel
    rect.y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * vel
        
    rect.centerx = rect.centerx % window.get_width()
    rect.centery = rect.centery % window.get_height()

    window.fill(0)
    pygame.draw.rect(window, (255, 0, 0), rect)
    pygame.display.flip()

pygame.quit()
exit()

Use this mate, it’ll work well, put it in your for loop.

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_a:
                playerX_change = -0.1
            if event.key == pygame.K_d:
                playerX_change = 0.1
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_a or event.key == pygame.K_d:
                playerX_change = 0

    playerX += playerX_change
    player(playerX, playerY)
    pygame.display.update()

a simpler way can be:
KEYDOWN event to set a moving flag. KEYUP event to clear the flag.
the movement process just check the flag every frame. if set move if unset then no move.

you can use KEYUP and KEYDOWN events.
you can continuously do your task while key is down and when key is up just stop that task

for event in pygame.event.get():
    if event.type == pygame.KEYUP:
        if event.key==K_DOWN:
            print("down key is not pressed")
    elif event.type == pygame.KEYDOWN:
        if event.key==K_DOWN:
            print('down key is not pressed now')
    
    pygame.event.clear() #optional only if your code requires 
    #this will clear all event and the for loop will executed only once

I suggest use the ‘clock’function.

while running:
spriteimg = plumberright
screen.blit(spriteimg,(x1, y1))
spriteimg_x = 0
spriteimg_y = 0
spriteimg_speed = 0.2
dt = clock.tick(120)
    if event.type == pygame.KEYDOWN:
         if event.key == pygame.K_UP:
             x1 = x1 + 0
             spriteimg_y -= spriteimg_speed
         elif event.key == pygame.K_DOWN:
             x1 = x1 + 0
             spriteimg_y += spriteimg_speed
         elif event.key == pygame.K_LEFT:
             spriteimg_x -= spriteimg_speed
             y1 = y1 + 0
         elif event.key == pygame.K_RIGHT:
             spriteimg_y -= spriteimg_speed
             y1 = y1 + 0
    x1 += spriteimg_speed * dt
    y1 += spriteimg_speed * dt

How about this way? and… i thought the ticks’s value is so high.. anyway, i hope this way helps you.

Leave a Reply

Your email address will not be published. Required fields are marked *