pygame 中的新循环的变量值未正确更新

Values of variables don't update properly for new loop in pygame

使用 pygame 和 python 3.7,我创建了一个游戏,其中中心 (250, 250) 的图像可以在屏幕上拖动并与半径碰撞,其中如果发生中断,下一个循环中的下一个图像会在准确的中心产生,第一个图像也位于该中心。尽管游戏按照我预期的方式运行,但原则上,它在快速鼠标速度下表现得很奇怪。在我的最小示例代码中,彩色圆圈应该在每​​个 while 循环中重新出现在确切的中心,但是,它们以某种方式无法正确更新,因此大部分时间都不会重新出现在屏幕中心(它们仅当我很早/适时释放鼠标按钮时才这样做)。我在 windows 和 mac 上测试了游戏并注意到在我的 mac 上,"lag" 似乎更糟。如果有人知道我该如何解决这个问题,我将非常感激。此外,游戏开始滞后并立即跳到下一个循环以实现真正快速的鼠标移动,我通过更改外接鼠标的速度来解决这个问题。 pygame 中鼠标移动过快是否有固有的修复方法?感谢所有建议,也许还有对我的代码想法的其他改进。

import pygame
import time
from time import sleep
import math

pygame.init()

gameDisplay = pygame.display.set_mode((500, 500))

clock = pygame.time.Clock()

background_surface = pygame.Surface((500, 500))

background_surface.fill((255, 255, 255))

colors = [(0,0,0), (253, 45, 0), (249, 253, 0), (32, 201, 5), (0, 210, 235)]

for color in colors:

    done = False

    a, b = 250, 250

    u, v = 250, 250

    while not done:

        clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
            elif event.type == pygame.MOUSEMOTION:
                if event.buttons[0]:
                    a += event.rel[0]
                    b += event.rel[1]


        rect = pygame.Rect(u, v, 0.001, 0.001)
        radius = 200
        corners = [rect.bottomleft, rect.bottomright, rect.topleft, rect.topright]
        dist = [math.sqrt((p[0] - a) ** 2 + (p[1] - b) ** 2) for p in corners]
        p_out = [i for i, d in enumerate(dist) if d > radius]

        if any(p_out):
            break

        gameDisplay.blit(background_surface, (0, 0))
        pygame.draw.circle(gameDisplay, color, (a,b), 50, 0)
        pygame.draw.circle(gameDisplay, (0,0,0), (250,250), 200, 2)
        pygame.display.flip()
    sleep(0.7)

pygame.quit()
quit()

[...] they somehow don't update properly and therefore reappear not at the center of the screen, most of the time (they only do when I release the mouse-button really early / well-timed) [...]

当然,请调查您的代码。您的代码中发生的第一件事是 ab 被修改:

while not done:
   # [...]

for event in pygame.event.get():
   if event.type == pygame.QUIT:
        done = True
    elif event.type == pygame.MOUSEMOTION:
        if event.buttons[0]:
            a += event.rel[0]
            b += event.rel[1]

如果 pygame.MOUSEMOTION 事件在队列中,则在绘制圆之前处理它。所以修改了圆的位置,不出现在中心
请注意,事件不反映鼠标的当前状态。它是一个通知,当它发生时存储在队列中,但事件处理可能会在以后完成。你实际上做的是处理一个事件,这个事件可能发生在过去。

在每个循环开始时使用状态 dragging,即 False。设置按下按钮时的状态(pygame.MOUSEBUTTONDOWN事件),释放按钮时重置状态(pygame.MOUSEBUTTONUP事件):

for color in colors:

    # [...]

    dragging = False
    while not done:

        clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    dragging = True
            elif event.type == pygame.MOUSEBUTTONUP:
                if event.button == 1:
                    dragging = False
            elif event.type == pygame.MOUSEMOTION:
                if dragging:
                    a += event.rel[0]
                    b += event.rel[1]

        # [...]