23

Currently the sprite only moves one pixel every time a key is pressed. How could I cause the plumber sprite to move constantly when the 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)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
enrique2334
  • 1,021
  • 3
  • 17
  • 32

6 Answers6

39

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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
qiao
  • 17,941
  • 6
  • 57
  • 46
4

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. It is a snapshot of the keys at that very moment The new state of the keys must be retrieved continuously in each frame. 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()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
1

Use this. 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()
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
FastFinge
  • 54
  • 3
0

A simpler way can be:

KEYDOWN event to set a moving flag. KEYUP event to clear the flag. For the movement process, just check the flag every frame. If set, move, and if unset then no move.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Bon Lee
  • 11
  • 1
  • 1
    This is much mor complicate and requires much more code than using `pygame.key.get_pressed` – Rabbid76 Aug 24 '21 at 14:00
  • Welcome to SO! Please answer the question asked to the best of your ability. For example, by providing some context with a code example. For more tips see [stackoverflow.com/help/how-to-answer](https://stackoverflow.com/help/how-to-answer) – fpersyn Aug 25 '21 at 08:19
0

You can use KEYUP and KEYDOWN events.

You can continuously do your task while a key is down and when the 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 events and the 'for' loop will be executed only once
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ajay Sahu
  • 186
  • 1
  • 7
-1

I suggest to 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...

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jun
  • 13
  • 5