python - Pygame 键盘输入事件滞后

标签 python animation pygame lag keyboard-input

我在使用pygame编写小程序后遇到了问题。该程序采用分割的 .GIF 动画并通过以下方式加载图像(gif 的帧):

pygame.image.load(filename)

这会返回一个 pygame 表面对象,然后将其附加到一个数组中。该程序将大约15 个帧加载到一个数组中,总共使用6 个数组

我遇到的问题是通过 while 循环接受输入时。循环播放其空闲动画并正常运行动画,但是,在接受来自键盘的输入时(从 pygame 的事件列表中获取输入...)

对于 pygame.event.get() 中的事件: 通过 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都是元组设置为(300, 240)

最佳答案

您的问题是您在主循环内创建了子循环:

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) 一次即可解决您的问题。

这是一个简单的示例,每秒更改动画图像 3 次,同时以 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)

enter image description here

关于python - Pygame 键盘输入事件滞后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21450780/

相关文章:

python - 如何在vispy中选择距离点击点最近的标记?

c++ - 在 Boost.Python : wrong type 中的类中存储和检索指针时出现 ArgumentError

python - 是否有类似字典的数据结构允许搜索 'key' 和 'value'

ios - UIScrollView内存分配上的动画内容

javascript - 取消所有Javascript的setTimeouts和setIntervals

ios - 等待执行 viewWillDisappear 直到自定义动画完成?

python - 马里奥在pygame中跑过屏幕太快

连接本地MySQL数据库的Python 3.2脚本

python - a*star 寻路可视化非常慢/python

python - 如何在 pygame 中在屏幕顶部显示分数?