Python 如何实现Pygame定时游戏循环?

Python 如何实现Pygame定时游戏循环?,python,pygame,Python,Pygame,我希望用Python编写一个更好的游戏循环,使用pygame.time.Clock(),并且我理解从主游戏循环中保留时间和去耦合渲染的概念,以便更好地利用滴答声。我还了解如何将时间延迟传递到渲染中,以便渲染正确的运动量,但我发现的唯一示例是用C#编写的,尽管我最初认为转换为Python相当简单,但它没有表现出来 我已经发现Pygame的Clock()已经计算出了最近两次调用.tick之间的毫秒数,并且我已经尝试调整我找到的示例代码,但我确实需要看看用Python编写的工作示例。以下是我到目前为止

我希望用Python编写一个更好的游戏循环,使用
pygame.time.Clock()
,并且我理解从主游戏循环中保留时间和去耦合渲染的概念,以便更好地利用滴答声。我还了解如何将时间延迟传递到渲染中,以便渲染正确的运动量,但我发现的唯一示例是用C#编写的,尽管我最初认为转换为Python相当简单,但它没有表现出来

我已经发现Pygame的
Clock()
已经计算出了最近两次调用.tick之间的毫秒数,并且我已经尝试调整我找到的示例代码,但我确实需要看看用Python编写的工作示例。以下是我到目前为止的想法:

FPS = 60
MS_PER_UPDATE = 1000 / FPS
lag = 0.0
clock = pygame.time.Clock()
running = True

# Do an initial tick so the loop has 2 previous ticks.
clock.tick(FPS)

while running:
    clock.tick(FPS)
    lag += clock.get_time()
    user_input()

    while lag >= MS_PER_UPDATE:
        update()
        lag -= MS_PER_UPDATE

    render(lag / MS_PER_UPDATE)

我不确定这一切在Pygame中是否值得,或者它是否已经在一些
时间
函数中得到了处理?我的游戏在笔记本电脑上运行得比较慢(预期),但我认为这样做可能会通过解耦合渲染,使我的主PC和笔记本电脑之间的FPS有所降低。有没有人有在Pygame中执行这些高级游戏循环的经验?我只希望它尽可能好…

只需花时间渲染最后一帧(称为增量时间),并将其传递给游戏对象,以便他们可以决定要做什么(例如,移动更多或更少)

下面是一个超级简单的示例:

import pygame

class Actor(pygame.sprite.Sprite):
    def __init__(self, *args):
        super().__init__(*args)
        self.image = pygame.Surface((32, 32))
        self.rect = pygame.display.get_surface().get_rect()
        self.image.fill(pygame.Color('dodgerblue'))

    def update(self, events, dt):
        self.rect.move_ip((1 * dt / 5, 2 * dt / 5))
        if self.rect.x > 500: self.rect.x = 0
        if self.rect.y > 500: self.rect.y = 0

def main():
    pygame.init()
    screen = pygame.display.set_mode((500, 500))
    sprites = pygame.sprite.Group()
    Actor(sprites)
    clock = pygame.time.Clock()
    dt = 0
    while True:

        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return

        sprites.update(events, dt)

        screen.fill((30, 30, 30))
        sprites.draw(screen)
        pygame.display.update()

        dt = clock.tick(60)

if __name__ == '__main__':
    main()

如果游戏速度降低到每秒60帧以下,
dt
会变大,
Actor
会移动更多以弥补损失的时间。

哇,这么简单吗?我想我和往常一样把事情复杂化了。谢谢@sloth,这看起来像是我想要的。我现在让我的游戏同时在PC和笔记本电脑上运行,它们现在都以完全相同的速度运行,尽管PC的速度是58-60 FPS,笔记本电脑的速度是40 FPS,这很完美。太棒了,再次感谢@sloth。我应该说,我没有直接将
dt
传递到
update()
中,而是将它除以
MS\u PER\u update
,它给出了一个因子(例如,如果
dt
是16ms,而
MS\u PER\u update
是16ms(60FPS)),则
dt
将作为
1
传入。如果
dt
为32ms,则作为
2
传入,以此类推,移动乘以dt因子)。我还需要调用一个额外的
。在循环之前勾选
,以给它第一个调用,否则,因为没有“2个以前的调用”然后
dt
从9000点以上开始!当我第一次这样做的时候,这真的破坏了我的图形,所以我需要一个初始的
。勾选
调用。中提琴!全部完成:)