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?
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.
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.
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.
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 .
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)
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
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With