Python Pygame键盘输入事件延迟
在用pygame编写了一个小程序之后,我遇到了一个问题。该程序通过以下方式获取split.GIF动画并加载图像(GIF帧): 这将返回一个pygame曲面对象,然后将其附加到数组中。程序总共使用6个数组将大约15帧加载到一个数组中 我遇到的问题是当通过我的while循环接受输入时。循环播放其空闲动画并运行动画,但是,在接受键盘输入时(从pygame的事件列表中获取输入…) pygame.event.get()中事件的Python Pygame键盘输入事件延迟,python,animation,pygame,lag,keyboard-input,Python,Animation,Pygame,Lag,Keyboard Input,在用pygame编写了一个小程序之后,我遇到了一个问题。该程序通过以下方式获取split.GIF动画并加载图像(GIF帧): 这将返回一个pygame曲面对象,然后将其附加到数组中。程序总共使用6个数组将大约15帧加载到一个数组中 我遇到的问题是当通过我的while循环接受输入时。循环播放其空闲动画并运行动画,但是,在接受键盘输入时(从pygame的事件列表中获取输入…) pygame.event.get()中事件的:通过pygame.KEYDOWN 有非常明显的延迟,导致无响应的动画集切换。如
:
通过pygame.KEYDOWN
有非常明显的延迟,导致无响应的动画集切换。如果我要用这种方法制作一个游戏,它必须被修复。我确信我的代码效率很低,但不创建暂停就足够了。任何帮助都会很棒
我猜呢pygame.clock.tick()
正在创建某种类型的事件延迟,但如果事件延迟是这样的话,我不确定如何着手解决这个问题
以下是我怀疑有问题的循环:
while running == 2:
pygame.display.flip()
#mouse = pygame.mouse.get_pos()
#events = pygame.event.get()
#(pygame.QUIT, pygame.KEYDOWN, pygame.KEYUP)
for event in pygame.event.get():
#event = pygame.event.wait()
if event.type == pygame.QUIT:
sys.exit(0)
elif event.type == pygame.KEYDOWN:
print event.key
wait = 0
if event.key == pygame.K_d:
tmpcache = wr
lastkey = "wr"
elif event.key == pygame.K_a:
tmpcache = wl
lastkey = "wl"
elif event.type == pygame.KEYUP:
wait = 1
if lastkey == "wr":
tmpcache = sr
elif lastkey == "wl":
tmpcache = sl
if wait == 1:
for frame in tmpcache:
screen.blit(test, (0,0))
screen.blit(frame, (currentchar.posx, currentchar.posy))
pygame.display.flip()
clock.tick(charfps)
else:
for frame in tmpcache:
screen.blit(test, (0,0))
screen.blit(frame, (currentchar.posx, currentchar.posy))
pygame.display.flip()
clock.tick(charfps)
此处未显示一些变量,但使用了:
charfps=30
currentchar.posx,currentchar.posy
都是元组设置在(300240)
您的问题是在主循环内创建子循环:
while running == 2:
pygame.display.flip()
for event in pygame.event.get():
...
for frame in tmpcache:
screen.blit(test, (0,0))
screen.blit(frame, (currentchar.posx, currentchar.posy))
pygame.display.flip()
clock.tick(charfps)
因此,如果tmpcache
中有15个元素,则调用clock.tick()
15次/帧,并且当代码在该子循环中运行时,不会继续事件
只需在每帧中调用pygame.display.flip()
和clock.tick(charfps)
一次就可以解决问题
下面是一个简单的示例,每秒更改动画图像三次,同时以60 FPS的速度运行:
import pygame
from collections import deque
pygame.init()
screen = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
# just some colored squares for our animation
def get_cache(colors):
tmp=[]
for c in colors:
s = pygame.surface.Surface((50,50))
s.fill(pygame.color.Color(c))
tmp.append(s)
return tmp
walk_left, walk_right = get_cache(('red', 'yellow', 'blue')), get_cache(('black', 'white', 'grey'))
rect = walk_left[0].get_rect(top=100, right=100)
cachedeque = deque(walk_left)
state = None
quit = False
# a simple variable to keep track of time
timer = 0
# a dict of {key: (animation, direction)}
moves = {pygame.K_LEFT: (walk_left, (-2, 0)),
pygame.K_RIGHT: (walk_right, ( 2, 0))}
while not quit:
quit = pygame.event.get(pygame.QUIT)
pygame.event.poll()
# state of the keys
keys = pygame.key.get_pressed()
# filter for the keys we're interessted in
pressed = ((key, _) for (key, _) in moves.iteritems() if keys[key])
key, (cache, dir) = next(pressed, (None, (None, None)))
# if a key of the 'moves' dict is pressed:
if key:
# if we change the direction, we need another animation
if state != key:
cachedeque = deque(cache)
state = key
# move the square
rect.move_ip(dir)
else:
state = None
screen.fill(pygame.color.Color('green'))
# display first image in cachedeque
screen.blit(cachedeque[0], rect)
# rotate cachedeque to the left, so the second image becomes the first
# do this three times a second:
if state and timer >= 1000./3:
cachedeque.rotate(-1)
timer = 0
# call flip() and tick() only once per frame
pygame.display.flip()
# keep track of how long it took to draw this frame
timer += clock.tick(60)
这个问题似乎离题了,因为它属于游戏开发,在游戏开发中会更好,但它仍然是关于编程的。我理解你的意思,因为每帧只更新一次显示器和时钟。然而,你给我的根本不起作用。当按下相应的键时,它只给我动画中的第二帧。我希望动画在循环中以30 fps的速度播放角色行走(总共15帧左右),这取决于是否按住关键点,而不会实际影响输入时间(在等待动画完成循环时产生延迟)。这肯定有助于我了解发生了什么,我以前从未使用过deque,我相信这将在未来的编程项目中帮助我。我用你教给我的技术更新了我的代码,现在效果很好,谢谢!
import pygame
from collections import deque
pygame.init()
screen = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
# just some colored squares for our animation
def get_cache(colors):
tmp=[]
for c in colors:
s = pygame.surface.Surface((50,50))
s.fill(pygame.color.Color(c))
tmp.append(s)
return tmp
walk_left, walk_right = get_cache(('red', 'yellow', 'blue')), get_cache(('black', 'white', 'grey'))
rect = walk_left[0].get_rect(top=100, right=100)
cachedeque = deque(walk_left)
state = None
quit = False
# a simple variable to keep track of time
timer = 0
# a dict of {key: (animation, direction)}
moves = {pygame.K_LEFT: (walk_left, (-2, 0)),
pygame.K_RIGHT: (walk_right, ( 2, 0))}
while not quit:
quit = pygame.event.get(pygame.QUIT)
pygame.event.poll()
# state of the keys
keys = pygame.key.get_pressed()
# filter for the keys we're interessted in
pressed = ((key, _) for (key, _) in moves.iteritems() if keys[key])
key, (cache, dir) = next(pressed, (None, (None, None)))
# if a key of the 'moves' dict is pressed:
if key:
# if we change the direction, we need another animation
if state != key:
cachedeque = deque(cache)
state = key
# move the square
rect.move_ip(dir)
else:
state = None
screen.fill(pygame.color.Color('green'))
# display first image in cachedeque
screen.blit(cachedeque[0], rect)
# rotate cachedeque to the left, so the second image becomes the first
# do this three times a second:
if state and timer >= 1000./3:
cachedeque.rotate(-1)
timer = 0
# call flip() and tick() only once per frame
pygame.display.flip()
# keep track of how long it took to draw this frame
timer += clock.tick(60)