Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Smooth Keyboard Movement in Pygame

I'm using this code to have a player sprite move around a screen when the arrow keys are pressed:

import pygame, sys, time
from pygame.locals import *

pygame.init()

FPS=30
fpsClock=pygame.time.Clock()

width=400
height=300
DISPLAYSURF=pygame.display.set_mode((width,height),0,32)
pygame.display.set_caption('Animation')
background=pygame.image.load('bg.png')


UP='up'
LEFT='left'
RIGHT='right'
DOWN='down'

sprite=pygame.image.load('down.png')
spritex=200
spritey=130
direction=DOWN


pygame.mixer.music.load('bgm.mp3')
pygame.mixer.music.play(-1, 0.0)
while True:
    DISPLAYSURF.blit(background,(0,0))

    DISPLAYSURF.blit(sprite,(spritex,spritey))

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

        if event.type == KEYDOWN:
            if (event.key == K_LEFT):
                spritex-=5
                sprite=pygame.image.load('left.png')
            elif (event.key == K_RIGHT):
                spritex+=5
                sprite=pygame.image.load('right.png')
            elif (event.key == K_UP):
                spritey-=5
                sprite=pygame.image.load('up.png')
            elif (event.key == K_DOWN):
                spritey+=5
                sprite=pygame.image.load('down.png')

    pygame.display.update()
    fpsClock.tick(FPS)

The image is able to actually move, but only 5 pixels when the key is pressed. I want for the image to keep moving while the key is held down (and to add basic collision detection with the window, but that's a different issue). What would make the image keep moving while the key is pressed down?

like image 279
oracleCreeper Avatar asked Dec 30 '12 01:12

oracleCreeper


People also ask

How do you get pressed keys in pygame?

To know which key was pressed, we have to check the event. key variable corresponds to which pygame keys. For example, the pygame key for the letter “A” is “K_a” then we will compare event. Key with K a and if it comes to be same that means the key “A” was pressed.

How do you move up and down in pygame?

In pygame the top left corner of the screen is (0,0) and the bottom right is (width, height). This means to move up we subtract from the y of our character and to move down we add to the y.

How do you make a sprite move continuously in pygame?

To move a sprite in Pygame, you must tell Python to redraw the sprite in its new location—and where that new location is. Since the Player sprite isn't always moving, make these updates a dedicated function within the Player class. Add this function after the control function you created earlier.

What is Keyup and Keydown in pygame?

KEYDOWN and pygame. KEYUP events when the keyboard buttons are pressed and released. Both events have a key attribute that is a integer ID representing every key on the keyboard. The pygame. KEYDOWN event has additional attributes unicode and scancode .


3 Answers

I suggest using variables to keep track of which arrow keys are pressed and which are not. You can use the KEYDOWN and KEYUP events to update the variables. Then you can adjust the position of the sprite each frame based on which keys are pressed. This also means you can easily set the speed of the sprite in different directions by changing how far it moves each frame.

EDIT:

Or as @monkey suggested, you can use key.get_pressed() instead.

Here's an untested example:

while True:
    DISPLAYSURF.blit(background,(0,0))

    DISPLAYSURF.blit(sprite,(spritex,spritey))

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

        if event.type == KEYDOWN:
            if (event.key == pygame.K_LEFT):
                sprite=pygame.image.load('left.png')
            elif (event.key == pygame.K_RIGHT):
                sprite=pygame.image.load('right.png')
            elif (event.key == pygame.K_UP):
                sprite=pygame.image.load('up.png')
            elif (event.key == pygame.K_DOWN):
                sprite=pygame.image.load('down.png')

    keys_pressed = pygame.key.get_pressed()

    if keys_pressed[pygame.K_LEFT]:
        spritex -= 5

    if keys_pressed[pygame.K_RIGHT]:
        spritex += 5

    if keys_pressed[pygame.K_UP]:
        spritey -= 5

    if keys_pressed[pygame.K_DOWN]:
        spritey += 5

    pygame.display.update()
    fpsClock.tick(FPS)
like image 126
grc Avatar answered Sep 23 '22 02:09

grc


I would suggest using the set_repeat function. Held keys generate multiple events, periodically(which is set by the function's parameters).This allows you to use your code unmodified (no need for extra variables).

The function prototype:

set_repeat(delay, interval)

The first parameter delay is the number of milliseconds before the first repeated pygame.KEYDOWN will be sent. After that another pygame.KEYDOWN will be sent every interval milliseconds. If no arguments are passed the key repeat is disabled.

Simply use this function before the main loop.

 pygame.key.set_repeat(10,10)

Source: http://www.pygame.org/docs/ref/key.html#pygame.key.set_repeat

like image 25
agent_Jay Avatar answered Sep 22 '22 02:09

agent_Jay


I did it like this:

import pygame, sys, time
from pygame.locals import *

pygame.init()

FPS=30
fpsClock=pygame.time.Clock()

width=400
height=300
DISPLAYSURF=pygame.display.set_mode((width,height),0,32)
pygame.display.set_caption('Animation')
background=pygame.image.load('bg.png')


UP='up'
LEFT='left'
RIGHT='right'
DOWN='down'

sprite=pygame.image.load('down.png')
spritex=200
spritey=130
direction=None

def move(direction, sprite, spritex, spritey):
    if direction:
        if direction == K_UP:
            spritey-=5
            sprite=pygame.image.load('up.png')
        elif direction == K_DOWN:
            spritey+=5
            sprite=pygame.image.load('down.png')
        if direction == K_LEFT:
            spritex-=5
            sprite=pygame.image.load('left.png')
        elif direction == K_RIGHT:
            spritex+=5
            sprite=pygame.image.load('right.png')
    return sprite, spritex, spritey

pygame.mixer.music.load('bgm.mp3')
pygame.mixer.music.play(-1, 0.0)
while True:
    DISPLAYSURF.blit(background,(0,0))

    DISPLAYSURF.blit(sprite,(spritex,spritey))

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

        if event.type == KEYDOWN:
            direction = event.key
        if event.type == KEYUP:
            if (event.key == direction):
                direction = None
    sprite, spritex, spritey = move(direction, sprite, spritex, spritey)

    pygame.display.update()
    fpsClock.tick(FPS)
like image 44
jgritty Avatar answered Sep 23 '22 02:09

jgritty