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":
{
"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":
{
@ -434,6 +435,12 @@ class Meter(GameChild):
else:
icon.hide()
def percent(self):
"""
Return amount as a percent of the full amount
"""
return self.amount / self.units
def update(self):
ds = self.get_display_surface()
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")
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):
"""
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.load_from_path("Spoopy.png", True)
# 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.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.load_from_path("alienAnimations/alienBoil", True)
for sprite in self.kool_man, self.visitor, self.spoopy:
@ -1650,7 +1672,7 @@ class Boss(Animation):
self.health = Health(self)
self.sword = Sword(self)
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.kool_man.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):
background.add_frameset(name="normal", switch=True)
background.load_from_path(f"bg/bg00{ii + 1}.png")
# Inverted background
background.add_frameset(name="inverted", switch=True)
frame = pygame.Surface(background.frames[0].get_size())
frame.fill((255, 255, 255))
frame.blit(background.frames[0], (0, 0), None, pygame.BLEND_RGB_SUB)
background.add_frame(frame)
# Darkened background
background.add_frameset(name="charging", switch=True)
frame = background.frames[0].copy()
mask = frame.copy()
mask.fill((80, 80, 80))
frame.blit(mask, (0, 0), None, pygame.BLEND_RGB_SUB)
frame.fill((80, 80, 80), None, pygame.BLEND_RGB_SUB)
background.add_frame(frame)
# 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.set_frameset("normal")
self.countdown = Countdown(self)
@ -1757,8 +1784,8 @@ class Boss(Animation):
elif index == 1:
dialogue.set_avatar(self.visitor_avatar)
dialogue.set_name("Visitor")
self.visitor.unhide()
self.visitor.set_frameset("normal")
self.visitor.hide()
self.play(self.enter_boss, play_once=True, delay=2000)
elif index == 2:
dialogue.set_avatar(self.spoopy_avatar)
dialogue.set_name("Spoopy")
@ -1804,6 +1831,7 @@ class Boss(Animation):
for background in self.backgrounds:
background.set_frameset("normal")
self.halt(self.end_hit_animation)
self.halt(self.warning)
def deactivate(self):
self.active = False
@ -1984,8 +2012,8 @@ class Boss(Animation):
self.get_game().chemtrails.challenge()
self.backgrounds[self.level_index].set_frameset("charging")
# Set each boss to its normal frameset
# for boss in (self.kool_man, self.visitor, self.spoopy):
# boss.set_frameset("normal")
for boss in (self.kool_man, self.visitor, self.spoopy):
boss.set_frameset("normal")
def choose_new_edge(self, edges):
while True:
@ -1997,6 +2025,9 @@ class Boss(Animation):
self.battle_finished = True
self.halt(self.brandish)
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.queue = []
self.brandish_complete = True
@ -2004,7 +2035,7 @@ class Boss(Animation):
if self.level_index == 0:
self.kool_man.set_frameset(0)
elif self.level_index == 1:
self.visitor.set_frameset(0)
self.visitor.set_frameset("hurt")
elif self.level_index == 2:
self.spoopy.set_frameset(0)
self.add_score()
@ -2099,13 +2130,42 @@ class Boss(Animation):
"""
Return boss's animation to normal
"""
for boss in (self.kool_man, self.visitor, self.spoopy):
boss.set_frameset("normal")
if not self.battle_finished:
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):
"""
Update graphics
"""
if self.active:
self.backgrounds[self.level_index].update()
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.advance_prompt.check_first_press():
self.advance_prompt.press_first()
@ -2123,12 +2183,14 @@ class Boss(Animation):
else:
self.time_elapsed += self.get_game().time_filter.get_last_frame_duration()
Animation.update(self)
# Update boss sprite
if self.level_index == 0:
self.kool_man.update()
elif self.level_index == 1:
self.visitor.update()
if self.brandish_complete:
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()
remaining_positions = list(reversed(self.queue[self.get_game().chemtrails.queue_index:]))
for ii, position in enumerate(remaining_positions):
@ -2144,6 +2206,10 @@ class Boss(Animation):
self.sword.update()
self.health.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):
if self.active:
@ -2431,7 +2497,6 @@ class Sword(Animation):
sprite.get_current_frameset().measure_rect()
sprite.update_location_size()
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():
if sprite.get_current_frameset().get_current_id() == sprite.get_current_frameset().order[-1]:
sprite.hide()

1
config
View File

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