I am working on a game that features the TARDIS from Doctor Who. I have chosen to animate the TARDIS materialization sequence by altering the alpha value of the surface. The method works and looks great, but there is one problem:
The timing of the sequence is inconsistent.
Sometimes it will be very fast, sometimes slower. Considering it is accompanied by a sound effect this makes it look pretty hokey.
So far I have tried timing it against the epoch (time.time()) and Pygame's time module by adding delays or waits of various milliseconds to no avail. Who would have thought Time Lord engineering would be so challenging? @_@
Here is the class without timing.
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)
The sound effect is approximately 8 seconds long. Any ideas would be appreciated.
UPDATE: The latest thing I have tried is to separate the alpha update from the blitting itself. Still no luck.
The presence or lack of various game objects does not seem to effect it. (It's randomly timed whether it's on a black screen, white screen, blitted multiple times, etc)
Code for Rabbid's answer:
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()
All render roughly the same result.
Ok I found the solution.
Rather than using the alpha level of the object as the trigger for the fluctuation, I added a variable (self.stage) and timed the increment of that variable with a timer (of which there are many options).
So the new function looks like this.
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)
With this as the timed function:
def tardis_mat_sequence():
if TardisTwo.stage < 8:
TardisTwo.stage += 1
else:
TardisTwo.stage = 1
Tardis_Timer.setstate('stop')
Conclusion: Cannot control the time of set_alpha directly. Let me know if anyone disagrees with this conclusion. Hope this solution helps someone in the future.