timer warning effect and visitor entrance animation

This commit is contained in:
frank 2022-02-28 21:34:18 -05:00
parent ad0c68aedb
commit e1ab123bdd
2 changed files with 80 additions and 14 deletions

93
NS.py
View File

@ -86,7 +86,8 @@ class NS(Game, Animation):
"time": "time":
{ {
"int": ["timer-max-time", "timer-start-time", "timer-addition", "sword-delay", "int": ["timer-max-time", "timer-start-time", "timer-addition", "sword-delay",
"attract-gif-length", "attract-board-length", "attract-reset-countdown"] "attract-gif-length", "attract-board-length", "attract-reset-countdown"],
"float": "timer-warning-start"
}, },
"input": "input":
{ {
@ -434,6 +435,12 @@ class Meter(GameChild):
else: else:
icon.hide() icon.hide()
def percent(self):
"""
Return amount as a percent of the full amount
"""
return self.amount / self.units
def update(self): def update(self):
ds = self.get_display_surface() ds = self.get_display_surface()
ds.blit(self.background, self.rect) ds.blit(self.background, self.rect)
@ -1617,6 +1624,19 @@ class Boys(Meter):
self.setup(background, rect, 60, (0, 255, 0), 3, "scrapeIcons/scrapeIcons_01.png") self.setup(background, rect, 60, (0, 255, 0), 3, "scrapeIcons/scrapeIcons_01.png")
class BossSprite(Sprite):
"""
"""
def shift_frame(self):
"""
"""
frameset = self.get_current_frameset()
if frameset.name == "entrance" and frameset.get_current_id() == frameset.order[-1]:
self.set_frameset("normal")
super().shift_frame()
class Boss(Animation): class Boss(Animation):
""" """
The Boss object also serves as the level object, and it is expected that only one of these objects is initialized. The Boss object also serves as the level object, and it is expected that only one of these objects is initialized.
@ -1640,9 +1660,11 @@ class Boss(Animation):
self.spoopy = Sprite(self) self.spoopy = Sprite(self)
self.spoopy.load_from_path("Spoopy.png", True) self.spoopy.load_from_path("Spoopy.png", True)
# Set up alien sprite with boil and hurt animations # Set up alien sprite with boil and hurt animations
self.visitor = Sprite(self, 42) self.visitor = BossSprite(self, 42)
self.visitor.add_frameset(name="hurt", switch=True) self.visitor.add_frameset(name="hurt", switch=True)
self.visitor.load_from_path("alienAnimations/alienHit", True) self.visitor.load_from_path("alienAnimations/alienHit", True)
self.visitor.add_frameset(name="entrance", switch=True)
self.visitor.load_from_path("alienAnimations/alienIntro", True)
self.visitor.add_frameset(name="normal", switch=True) self.visitor.add_frameset(name="normal", switch=True)
self.visitor.load_from_path("alienAnimations/alienBoil", True) self.visitor.load_from_path("alienAnimations/alienBoil", True)
for sprite in self.kool_man, self.visitor, self.spoopy: for sprite in self.kool_man, self.visitor, self.spoopy:
@ -1650,7 +1672,7 @@ class Boss(Animation):
self.health = Health(self) self.health = Health(self)
self.sword = Sword(self) self.sword = Sword(self)
self.register(self.brandish, self.cancel_flash, self.show_introduction_dialogue, self.show_end_dialogue, self.end_dialogue, self.register(self.brandish, self.cancel_flash, self.show_introduction_dialogue, self.show_end_dialogue, self.end_dialogue,
self.end_player_damage, self.end_hit_animation) self.end_player_damage, self.end_hit_animation, self.warning, self.enter_boss)
self.register(self.flash_player_damage, interval=100) self.register(self.flash_player_damage, interval=100)
self.kool_man.add_frameset([0], name="normal", switch=True) self.kool_man.add_frameset([0], name="normal", switch=True)
self.spoopy.add_frameset([0], name="normal", switch=True) self.spoopy.add_frameset([0], name="normal", switch=True)
@ -1663,16 +1685,21 @@ class Boss(Animation):
for ii, background in enumerate(self.backgrounds): for ii, background in enumerate(self.backgrounds):
background.add_frameset(name="normal", switch=True) background.add_frameset(name="normal", switch=True)
background.load_from_path(f"bg/bg00{ii + 1}.png") background.load_from_path(f"bg/bg00{ii + 1}.png")
# Inverted background
background.add_frameset(name="inverted", switch=True) background.add_frameset(name="inverted", switch=True)
frame = pygame.Surface(background.frames[0].get_size()) frame = pygame.Surface(background.frames[0].get_size())
frame.fill((255, 255, 255)) frame.fill((255, 255, 255))
frame.blit(background.frames[0], (0, 0), None, pygame.BLEND_RGB_SUB) frame.blit(background.frames[0], (0, 0), None, pygame.BLEND_RGB_SUB)
background.add_frame(frame) background.add_frame(frame)
# Darkened background
background.add_frameset(name="charging", switch=True) background.add_frameset(name="charging", switch=True)
frame = background.frames[0].copy() frame = background.frames[0].copy()
mask = frame.copy() frame.fill((80, 80, 80), None, pygame.BLEND_RGB_SUB)
mask.fill((80, 80, 80)) background.add_frame(frame)
frame.blit(mask, (0, 0), None, pygame.BLEND_RGB_SUB) # Red background
background.add_frameset(name="warning", switch=True)
frame = background.frames[0].copy()
frame.fill((0, 150, 150), None, pygame.BLEND_RGB_SUB)
background.add_frame(frame) background.add_frame(frame)
background.set_frameset("normal") background.set_frameset("normal")
self.countdown = Countdown(self) self.countdown = Countdown(self)
@ -1757,8 +1784,8 @@ class Boss(Animation):
elif index == 1: elif index == 1:
dialogue.set_avatar(self.visitor_avatar) dialogue.set_avatar(self.visitor_avatar)
dialogue.set_name("Visitor") dialogue.set_name("Visitor")
self.visitor.unhide() self.visitor.hide()
self.visitor.set_frameset("normal") self.play(self.enter_boss, play_once=True, delay=2000)
elif index == 2: elif index == 2:
dialogue.set_avatar(self.spoopy_avatar) dialogue.set_avatar(self.spoopy_avatar)
dialogue.set_name("Spoopy") dialogue.set_name("Spoopy")
@ -1804,6 +1831,7 @@ class Boss(Animation):
for background in self.backgrounds: for background in self.backgrounds:
background.set_frameset("normal") background.set_frameset("normal")
self.halt(self.end_hit_animation) self.halt(self.end_hit_animation)
self.halt(self.warning)
def deactivate(self): def deactivate(self):
self.active = False self.active = False
@ -1984,8 +2012,8 @@ class Boss(Animation):
self.get_game().chemtrails.challenge() self.get_game().chemtrails.challenge()
self.backgrounds[self.level_index].set_frameset("charging") self.backgrounds[self.level_index].set_frameset("charging")
# Set each boss to its normal frameset # Set each boss to its normal frameset
# for boss in (self.kool_man, self.visitor, self.spoopy): for boss in (self.kool_man, self.visitor, self.spoopy):
# boss.set_frameset("normal") boss.set_frameset("normal")
def choose_new_edge(self, edges): def choose_new_edge(self, edges):
while True: while True:
@ -1997,6 +2025,9 @@ class Boss(Animation):
self.battle_finished = True self.battle_finished = True
self.halt(self.brandish) self.halt(self.brandish)
self.halt(self.cancel_flash) self.halt(self.cancel_flash)
self.halt(self.warning)
self.halt(self.flash_player_damage)
self.halt(self.end_player_damage)
self.sword.reset() self.sword.reset()
self.queue = [] self.queue = []
self.brandish_complete = True self.brandish_complete = True
@ -2004,7 +2035,7 @@ class Boss(Animation):
if self.level_index == 0: if self.level_index == 0:
self.kool_man.set_frameset(0) self.kool_man.set_frameset(0)
elif self.level_index == 1: elif self.level_index == 1:
self.visitor.set_frameset(0) self.visitor.set_frameset("hurt")
elif self.level_index == 2: elif self.level_index == 2:
self.spoopy.set_frameset(0) self.spoopy.set_frameset(0)
self.add_score() self.add_score()
@ -2099,13 +2130,42 @@ class Boss(Animation):
""" """
Return boss's animation to normal Return boss's animation to normal
""" """
for boss in (self.kool_man, self.visitor, self.spoopy): if not self.battle_finished:
boss.set_frameset("normal") for boss in (self.kool_man, self.visitor, self.spoopy):
boss.set_frameset("normal")
def warning(self):
"""
Use this method as an animation to create a warning flash of the background that flashes according to the
amount of time left in the player's timer object.
"""
time_left = self.get_game().chemtrails.timer.percent()
warning_threshold = self.get_configuration("time", "timer-warning-start")
background = self.backgrounds[self.level_index]
if time_left > warning_threshold:
background.set_frameset("normal")
self.halt(self.warning)
else:
if background.get_current_frameset().name == "normal":
background.set_frameset("warning")
self.play(self.warning, play_once=True, delay=50)
else:
background.set_frameset("normal")
self.play(self.warning, play_once=True, delay=time_left / warning_threshold * 400)
def enter_boss(self):
self.visitor.unhide()
self.visitor.get_current_frameset().reset()
self.visitor.set_frameset("entrance")
def update(self): def update(self):
"""
Update graphics
"""
if self.active: if self.active:
self.backgrounds[self.level_index].update() self.backgrounds[self.level_index].update()
dialogue = self.get_game().dialogue dialogue = self.get_game().dialogue
# Handle the continue countdown or increase time elapsed if the continue screen
if self.countdown.active and dialogue.active and self.get_game().chemtrails.boys.amount > 0: if self.countdown.active and dialogue.active and self.get_game().chemtrails.boys.amount > 0:
if self.advance_prompt.check_first_press(): if self.advance_prompt.check_first_press():
self.advance_prompt.press_first() self.advance_prompt.press_first()
@ -2123,12 +2183,14 @@ class Boss(Animation):
else: else:
self.time_elapsed += self.get_game().time_filter.get_last_frame_duration() self.time_elapsed += self.get_game().time_filter.get_last_frame_duration()
Animation.update(self) Animation.update(self)
# Update boss sprite
if self.level_index == 0: if self.level_index == 0:
self.kool_man.update() self.kool_man.update()
elif self.level_index == 1: elif self.level_index == 1:
self.visitor.update() self.visitor.update()
if self.brandish_complete: if self.brandish_complete:
if self.queue is not None: if self.queue is not None:
# Draw ghosts of the upcoming moves fading more as the move goes futher back in the queue
self.alien_arm.unhide() self.alien_arm.unhide()
remaining_positions = list(reversed(self.queue[self.get_game().chemtrails.queue_index:])) remaining_positions = list(reversed(self.queue[self.get_game().chemtrails.queue_index:]))
for ii, position in enumerate(remaining_positions): for ii, position in enumerate(remaining_positions):
@ -2144,6 +2206,10 @@ class Boss(Animation):
self.sword.update() self.sword.update()
self.health.update() self.health.update()
self.countdown.update() self.countdown.update()
# Trigger the warning effect if time is running out
if self.get_game().chemtrails.life.amount > 0 and not self.is_playing(self.warning, include_delay=True) and \
self.get_game().chemtrails.timer.percent() <= self.get_configuration("time", "timer-warning-start"):
self.play(self.warning, play_once=True)
def update_dialogue(self): def update_dialogue(self):
if self.active: if self.active:
@ -2431,7 +2497,6 @@ class Sword(Animation):
sprite.get_current_frameset().measure_rect() sprite.get_current_frameset().measure_rect()
sprite.update_location_size() sprite.update_location_size()
sprite.location.center = center_save sprite.location.center = center_save
# sprite.move(*get_step(sprite.location.center, end, 4))
elif sprite.get_current_frameset().name == "explode" and not sprite.is_hidden(): elif sprite.get_current_frameset().name == "explode" and not sprite.is_hidden():
if sprite.get_current_frameset().get_current_id() == sprite.get_current_frameset().order[-1]: if sprite.get_current_frameset().get_current_id() == sprite.get_current_frameset().order[-1]:
sprite.hide() sprite.hide()

1
config
View File

@ -53,6 +53,7 @@ serial = True
timer-max-time = 10000 timer-max-time = 10000
timer-start-time = 7000 timer-start-time = 7000
timer-addition = 1000 timer-addition = 1000
timer-warning-start = 0.4
sword-delay = 300 sword-delay = 300
attract-gif-length = 10000 attract-gif-length = 10000
attract-board-length = 3600 attract-board-length = 3600