运行 乒乓球游戏的球动画真的很垃圾

ball animation is really junky while running pong game

球动画 运行 程序非常卡顿,我不明白为什么。 这只是程序的开始,因此请忽略游戏尚未准备好运行的事实。

这是代码:https://www.codepile.net/pile/dqKZa8OG

我希望球移动顺畅而不卡顿。 另外,我该怎么做才能让程序在每次更新后删除球的最后位置?

这不是 "junky" 因为计时器,你只能看到更新,因为你可能同时移动鼠标,然后你每次移动它都会更新球的位置(这是错误的,因为您随时更新位置 任何 事件被处理)。

问题是您以错误的方式使用了 Clockpygame.time.Clock class 创建了一个 «object that can be used to track 一个时间量»,这意味着它不是一个可以 "react" 一旦超时的计时器。根据您提供的 fps 参数,您调用的 tick 方法仅更新当前时钟,返回自上次调用 tick 本身以来经过的毫秒数。

您需要的是设置 一个计时器,可以使用特定的 eventid 仅用于更新。此外,由于您正在根据事件更新球的位置,如果您移动鼠标(或调用任何其他事件)使球移动得更快,即使它不应该移动,您也会获得更多移动 - 这就是您'将需要 Clock 对象。

# I'm using a smaller speed, otherwise it'll be too fast; it should 
# depend on the window size to ensure that bigger windows don't get 
# slower speeds
ball_velocity = .2
fps = 60
UPDATEEVENT = 24

[...]

def start_move_ball(angle):
    ticks = clock.tick()
    speed = ball_velocity * ticks
    # "global ball" is not required, as you are assigning values to an 
    # existing object, not declaring it everytime.
    # You can also use in-place operations to set the speeds, which is 
    # better for readability too.
    ball[0] += angle[0] * speed
    ball[1] += angle[1] * speed

def main_loop():
    angle = choose_angle()
    pygame.time.set_timer(UPDATEEVENT, 1000 // fps)
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                return False
            # update only if necessary!
            elif event.type == UPDATEEVENT:
                window.fill((0,0,0))
                start_move_ball(angle)
                draw_mid(window)
                draw_players(window)
                draw_ball(window)
                pygame.display.flip()

定时器设置在while周期之外,因为它会在每个时间间隔自动发送事件。您也可以将其保留在 withinwhile 中(在这种情况下 once=True 参数并不是真正需要的,因为它会根据相同的 eventid 自动更新计时器) ,但没有多大意义,因为 set_timer 总是在 之后 第一次设置时触发事件。
我使用 24 (pygame.USEREVENT) 作为事件 ID,但您可以按照 event 文档中的建议将其 ID 设置为 pygame.NUMEVENTS - 1。如果出于任何原因你想停止计时器,只需使用 pygame.time.set_timer(eventid, 0) 并且该 eventid(在本例中为 24)的计时器将不会再次启动。

除此之外还有一些建议:

  1. 删除 draw_mid(window) 中的 pygame.display.update() 行,因为它会导致绘画时出现闪烁。
  2. 避免对 link 代码使用外部服务(这不是你的情况,但如果代码太长,首先尝试将其减少到最小的、可重现的示例,最终留下所有相关部分),如他们可能在将来的某个时候变得不可用,从而使面临类似问题并在您发布后的某个时间阅读您的答案的人难以理解您的问题。