如何在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 中随着时间的推移控制某些东西,你有两个选择:
使用pygame.time.get_ticks()
测量时间并实现根据时间控制对象的逻辑。
使用定时器事件。在事件队列中使用 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的时间。
如果有人不同意这个结论,请告诉我。
希望这个解决方案对以后的人有所帮助。
我正在开发一款以《神秘博士》中的 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 中随着时间的推移控制某些东西,你有两个选择:
使用
pygame.time.get_ticks()
测量时间并实现根据时间控制对象的逻辑。使用定时器事件。在事件队列中使用
pygame.time.set_timer()
to repeatedly create aUSEREVENT
。事件发生时更改对象状态。
例如:
好的,我找到了解决方案。
我没有使用对象的 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的时间。 如果有人不同意这个结论,请告诉我。 希望这个解决方案对以后的人有所帮助。