Pygame 图像在没有正确输入的情况下移动

Pygame image moving without proper input

我最近开始对 pygame 进行一些修补,并编写了这段代码(按照教程):

import pygame

pygame.init()
display_width = 1920
display_height = 1080
black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
gameDisplay = pygame.display.set_mode((display_width,display_height))

pygame.display.set_caption("Galvadon's Adventure")

clock = pygame.time.Clock()

galvadon = pygame.image.load("galvadonModelVersion1.0.png")

def galvadonIsHere(x,y):
    gameDisplay.blit(galvadon,(x,y))

x = (display_width * 0.30)
y = (display_height * 0.2)
y_change = 0

crashed = False

while not crashed:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            crashed = True
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_DOWN:
                y_change = 5
            elif event.key == pygame.K_UP:
                y_change = -5
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                    y_change = 0
        y += y_change

        gameDisplay.fill(white) 
        galvadonIsHere(x,y)
        print(event)
        pygame.display.update()
        clock.tick(30)

pygame.quit()
quit() 

并且在一定程度上这段代码有效,问题是在我使用向上和向下箭头移动图像后,图像开始响应任何鼠标移动,只是沿着它最后移动的方向滑动。我可能错过了一些东西,但我似乎无法找到它是什么。我查看了各种网站寻找答案,但我找不到任何人问类似的问题,因此我为什么做这个话题。

您的问题出在 while 循环中。 keyup 的 if 语句位于 keydown 的 if 语句中,因此它阻止了它的工作。以下解决了您的问题:

while not crashed:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            crashed = True
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_DOWN:
                y_change = 5
            elif event.key == pygame.K_UP:
                y_change = -5
        else:
            y_change = 0

希望对您有所帮助。

您可以在这里做得更好。但让我们从解决问题开始。

'Bug' 是在您按下按键后,y_change 被设置并且不会为下一个引擎循环重置。这应该可以帮助您:

...
while not crashed:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            crashed = True
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_DOWN:
                y_change = 5
            elif event.key == pygame.K_UP:
                y_change = -5
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                    y_change = 0
        y += y_change

        gameDisplay.fill(white)
        galvadonIsHere(x, y)
        print(event)
        pygame.display.update()
        clock.tick(30)

        y_change = 0
...

请密切注意我代码段中的最后一行。在这里你重置 y_change 所以在下一个引擎循环中,无论发生或不发生,它都不会影响你的图像的位置。

重构和改进

首先,您可以同意检查 event 类型是否为 KEY_DOWN 并嵌套检查它是否是特定的按键按钮,阅读和使用起来都很痛苦。更不用说你检查 event 类型是否为 KEYUP,即使你知道这里是 KEYDOWN

    if event.type == pygame.KEYDOWN:
    ...
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                y_change = 0

所以,我所做的是定义辅助函数,它可以是通常的一个或 lambda。现在,许多人会争辩说 lambda 函数会影响可读性,但在这里它肯定可以帮助您进行这些检查。

示例:

key_pressed = lambda event, key: event.type == pygame.KEYDOWN and event.key == key

while not crashed:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            crashed = True
            break
        elif key_pressed(event, pygame.K_DOWN):
            y_change = 5
        elif key_pressed(event, pygame.K_UP):
            y_change = -5
        else:
            y_change = 0

        y += y_change

        gameDisplay.fill(white)
        galvadonIsHere(x, y)
        print(event)
        pygame.display.update()
        clock.tick(30)

        y_change = 0

还有一点,注意在有pygame.QUIT事件的情况下。 break 退出 for 循环,然后 while 循环也结束。这样您就不会处理任何排队的事件,也不会更新和 blit 图像。