[英]Smooth Keyboard Movement in Pygame
当按下箭头键时,我正在使用此代码让玩家精灵在屏幕上移动:
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)
图像能够实际移动,但按下按键时只能移动5个像素。 我希望图像在按住键的同时保持移动(并且在窗口中添加基本的碰撞检测,但这是一个不同的问题)。 当按下按键时,图像会继续移动的原因是什么?
我建议使用变量来跟踪哪些箭头键被按下,哪些不是。 您可以使用KEYDOWN
和KEYUP
事件来更新变量。 然后,您可以根据按下的键调整每帧精灵的位置。 这也意味着您可以通过改变每帧移动的距离,轻松地在不同方向上设置精灵的速度。
编辑:
或者如@monkey建议的那样,您可以使用key.get_pressed()代替。
这是一个未经测试的例子:
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)
我建议使用set_repeat函数。 Held键定期生成多个事件(由函数的参数设置)。这允许您不加修改地使用您的代码(不需要额外的变量)。
功能原型:
set_repeat(延迟,间隔)
第一个参数延迟是第一个重复的pygame.KEYDOWN发送之前的毫秒数。 之后,每隔一个毫秒发送另一个pygame.KEYDOWN。 如果没有传递参数,则禁用密钥重复。
只需在主循环之前使用此功能。
pygame.key.set_repeat(10,10)
资料来源: http : //www.pygame.org/docs/ref/key.html#pygame.key.set_repeat
我是这样做的:
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)
我会通过在循环内采取略微不同的动作来做到这一点。
要更新精灵,我首先检查KEYDOWN
事件,然后根据它设置direction
。 然后,我会根据direction
更新sprite
, spritex
和spritey
。 然后,我会检查KEYUP
事件并根据需要设置direction
(如果适用)。
以下是我编写代码的方法:
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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.