Pygame按键按下的检测

3
什么是Pygame中惯用的方式来告诉它只要按下一个键就一直运行某些东西?使用pygame.key.get_pressed()[pygame.K_p]==True或者pygame.mouse.get_pressed()==(1,0,0)时,似乎只有当按键或按钮被按下时才会有反应。例如,应该使用while循环吗?
我运行以下代码,只有在按下键/按钮时才会在shell中打印:
def main():
done = True
while done:
    for i in pygame.event.get():
        if pygame.key.get_pressed()[pygame.K_a] == 1:
            print "Key a is being pressed..."
        elif i.type == KEYDOWN and i.key == pygame.K_q:
            done = 0
    pygame.display.update()
pygame.quit()
main()

2
不要在for ... in pygame.event.get()内部使用get_pressed()。你会重复执行该函数很多次——如果有很多事件——或者零次——如果没有事件的话。 - furas
2个回答

5

事件 KEYDOWN 意味着“按键从未按下变成按下” - 它并不意味着“按键一直被按住不放”

enter image description here

当您开始按键时,它会生成事件KEYDOWN,并且pygame.event.get()返回非空列表-并且for循环可以执行if pygame.event.get() 当您按住键时,它不会生成事件KEYDOWN,并且pygame.event.get()返回空列表-并且for循环不执行if pygame.event.get() 您的代码应该如下所示
running = True
while running:
    # check events 
    for event in pygame.event.get():
        if event.type == KEYDOWN:
            if event.key == pygame.K_q:
               running = False

    # do it outside of `for event` loop
    # it is executed many times 
    if pygame.key.get_pressed()[pygame.K_a]: 
        print "Key is hold pressed..."

    pygame.display.update()

或 - 当您只需要执行一次某些操作时

key_A_pressed = False

running = True
while running:
    # check events 
    for event in pygame.event.get():
        if event.type == KEYDOWN:
            if event.key == pygame.K_q:
               running = False

            elif event.key == pygame.K_a:
               key_A_pressed = True

               # it is executed only once
               print "Key A - start pressing"

        if event.type == KEYUP:
            if event.key == pygame.K_a:
               key_A_pressed = False

               # it is executed only once
               print "Key A - stop pressing"

    # do it only once - outside of `for event` loop
    # it is executed many times 
    #if pygame.key.get_pressed()[pygame.K_a]: 
    # or
    if key_A_pressed:
        print "Key A is held pressed..."

    pygame.display.update()

谢谢,如果我理解正确的话,按住键或按钮不算作事件?所以你根本没有使用 pygame.key.get_pressed 吗?如果可以用 event.type==KEYDOWN 来模拟按住键,那么应该在什么时候和地方使用呢? - user4813927

2

您应该使用:

def main():
    done = False
    while not done:
        for i in pygame.event.get():
            if i.type == KEYDOWN and i.key == pygame.K_q:
                done = True

        pressed = pygame.key.get_pressed()     
        if pressed[pygame.K_a]:
            print "Key a is being pressed..."

        pygame.display.update()
    pygame.quit()

if __name__ == '__main__':
    main()

你的代码问题在于,你只在迭代所有接收到的事件时检查按下的键;所以如果没有事件,print "Key a is being pressed..." 部分将永远不会被执行。
只需将其放在事件循环之外即可。
此外,你不需要显式地与 True 进行比较;惯用的/Pythonic 的方法是直接使用 if pressed[pygame.K_a]:

谢谢你的回答。我觉得我有些误解了;这意味着key.get_pressed应该在每个while循环中刷新,以便给出连续的输出?那么,那种选项和在while循环之外编写if event.type==KEYDOWN and event.key==pygame.K_a之间会有什么区别呢?我尝试了两种方法,它们似乎具有相同的效果。 - user4813927
当您按下一个键时,会生成一个 KEYDOWN 事件。如果您释放了键,则会生成一个 KEYUP 事件。按住一个键不会创建新的事件(除非您启用了按键重复,但您不应该这样做)。 - sloth
我明白了。你能举个例子说明何时应该明确地使用 key.get_pressed 吗? - user4813927
每次你想知道一个键是否被按下(通常用于像这样的东西:如果按下左箭头,则继续向左移动)。 - sloth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接