可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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?
回答1:
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)
回答2:
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
回答3:
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)
回答4:
I would do this by taking a slightly different course of action inside the loop.
To update the sprite, I would first check for a KEYDOWN
event and then set direction
based on that. Then, I would update sprite
, spritex
, and spritey
based on direction
. Then, I would check for KEYUP
events and set direction
based on that, if appropriate.
Here's how I might code it:
sprite=pygame.image.load('down.png')
spritex=200
spritey=130
direction='down'
dir_from_key = {
K_LEFT: 'left',
K_RIGHT: 'right',
K_UP: 'up',
K_DOWN: '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))
# Get all the events for this tick into a list
events = list(pygame.event.get())
quit_events = [e for e in events if e.type == QUIT]
keydown_events = [e for e in events if e.type == KEYDOWN
and e.key in dir_from_key]
keyup_events = [e for e in events if e.type == KEYUP
and e.key in dir_from_key]
# If there's no quit event, then the empty list acts like false
if quit_events:
pygame.quit()
sys.exit()
# Non-last key down events will be overridden anyway
if keydown_events:
direction = dir_from_key[keydown_events[-1].key]
# Change location and image based on direction
if direction == 'left':
spritex-=5
sprite=pygame.image.load('left.png')
elif direction == 'right':
spritex+=5
sprite=pygame.image.load('right.png')
elif direction == 'up':
spritey-=5
sprite=pygame.image.load('up.png')
elif direction == 'down':
spritey+=5
sprite=pygame.image.load('down.png')
# If there's a keyup event for the current direction.
if [e for e in keyup_events if dir_from_key[e.key] == direction]:
direction = None
pygame.display.update()
fpsClock.tick(FPS)