如何在Pygame中准确调节时序?

How to accurately regulate timed sequences in Pygame?

我正在开发一款以《神秘博士》中的 TARDIS 为特色的游戏。我选择通过改变表面的 alpha 值来为 TARDIS 物化序列设置动画。该方法有效且看起来不错,但有一个问题:

序列的时间不一致。

有时候会很快,有时候会比较慢。考虑到它伴随着声音效果,这使它看起来很虚伪。

到目前为止,我已经尝试通过添加延迟或等待各种毫秒来针对纪元 (time.time()) 和 Pygame 的时间模块计时,但无济于事。谁会想到时间领主工程会如此具有挑战性? @_@

这里是没有计时的class

class Tardis:
    def __init__(self, display):
        self.pos = (HALF_SCREEN_WIDTH, HALF_SCREEN_HEIGHT)
        self.size = (170, 300)
        self.image = pygame.image.load('Images/Tardis2.png')
        self.image = pygame.transform.scale(self.image, self.size).convert_alpha()
        self.alpha = 255
        self.rect = self.image.get_rect()
        self.rect.center = self.pos
        self.display = display
        self.state = 'landed'
        self.page = 'Game'
        self.collision = pygame.rect.Rect(0, 0, self.rect.width // 1.2, self.rect.height // 15)
        self.collision.midbottom = self.rect.midbottom
        G_OBJECT_LIST.append(self)

    def draw(self):
        if self.state == 'demat 1':
            self.alpha -= 1
            if self.alpha < 80:
                self.state = 'demat 2'
        if self.state == 'demat 2':
            self.alpha += 1
            if self.alpha > 180:
                self.state = 'demat 3'
        if self.state == 'demat 3':
            self.alpha -= 1
            if self.alpha == 0:
                self.state = 'in flight'
        if self.state == 'mat 1':
            self.alpha += 1
            if self.alpha > 100:
                self.state = 'mat 2'
        if self.state == 'mat 2':
            self.alpha -= 1
            if self.alpha < 50:
                self.state = 'mat 3'
        if self.state == 'mat 3':
            self.alpha += 1
            if self.alpha == 255:
                self.state = 'landed'
        self.image.set_alpha(self.alpha)
        self.display.blit(self.image, self.rect.topleft)

音效时长约8秒。任何想法将不胜感激。

更新: 我最近尝试的是将 alpha 更新与 blitting 本身分开。仍然没有运气。

各种游戏对象的存在与否似乎并不影响它。 (黑屏、白屏、多次blitted等随机定时)

兔子的回答代码:

OPTION 1
        if pygame.time.get_ticks() % 2 == 0:
            TardisTwo.update_alpha()
OPTION 2
        if pygame.time.get_ticks() - interval > d_time:
            d_time += interval
            TardisTwo.update_alpha()
OPTION 3
        for event in pygame.event.get():
            if event.type == pygame.USEREVENT:
                TardisTwo.update_alpha()
OPTION 4
        pygame.time.delay(17)
        TardisTwo.update_alpha()

所有渲染结果大致相同。

如果你想在 Pygame 中随着时间的推移控制某些东西,你有两个选择:

  1. 使用pygame.time.get_ticks()测量时间并实现根据时间控制对象的逻辑。

  2. 使用定时器事件。在事件队列中使用 pygame.time.set_timer() to repeatedly create a USEREVENT。事件发生时更改对象状态。

例如:



好的,我找到了解决方案。

我没有使用对象的 alpha 级别作为波动的触发器,而是添加了一个变量 (self.stage) 并使用计时器(有很多选项)为该变量的增量计时.

所以新函数看起来像这样。

    def update_alpha(self):
        if self.state == 'demat':
            if self.alpha > 0:
                if self.stage % 2 == 0:
                    self.alpha += 1
                else:
                    self.alpha -= 2
            else:
                self.state = 'in flight'
        if self.state == 'mat':
            if self.alpha < 255:
                if self.stage % 2 == 0:
                    self.alpha -= 1
                else:
                    self.alpha += 2
            else:
                self.state = 'landed'
        self.image.set_alpha(self.alpha)

以此为定时功能:

def tardis_mat_sequence():
    if TardisTwo.stage < 8:
        TardisTwo.stage += 1
    else:
        TardisTwo.stage = 1
        Tardis_Timer.setstate('stop')

结论:无法直接控制set_alpha的时间。 如果有人不同意这个结论,请告诉我。 希望这个解决方案对以后的人有所帮助。