diff --git a/NS.py b/NS.py index 2775e3a..ca50f3c 100644 --- a/NS.py +++ b/NS.py @@ -7,7 +7,6 @@ from glob import iglob from os.path import basename, join from threading import Thread from serial import Serial -from PIL import Image, ImageDraw from pygame import Surface, Color from pygame.event import clear @@ -27,7 +26,8 @@ from lib.pgfw.pgfw.Animation import Animation from lib.pgfw.pgfw.Audio import SoundEffect from lib.pgfw.pgfw.extension import ( get_step, get_step_relative, get_delta, reflect_angle, - render_box, get_hsla_color, get_hue_shifted_surface + render_box, get_hsla_color, get_hue_shifted_surface, + get_color_swapped_surface ) from lib.pgfw.pgfw.gfx_extension import aa_filled_polygon @@ -44,6 +44,17 @@ class NS(Game, Animation): def __init__(self): Game.__init__(self) + self.get_configuration().type_declarations.add_chart( + { + "time": + { + "int": ["timer-max-time", "timer-start-time", "timer-addition", "sword-delay"] + }, + "input": + { + "bool": "serial" + } + }) Animation.__init__(self, self) self.load_sfx() self.subscribe(self.respond, KEYDOWN) @@ -60,17 +71,6 @@ class NS(Game, Animation): self.dialogue = Dialogue(self) self.chemtrails = Chemtrails(self) self.boss = Boss(self) - self.get_configuration().type_declarations.add_chart( - { - "time": - { - "int": ["timer-max-time", "timer-start-time", "timer-addition", "sword-delay"] - }, - "input": - { - "bool": "serial" - } - }) if self.serial_enabled(): self.serial_kill = False self.serial_data = 0 @@ -222,6 +222,50 @@ class Button(Sprite): self.add_frame(frame) +class Meter(GameChild): + + SPACING = 12 + + def __init__(self, parent): + GameChild.__init__(self, parent) + + def setup(self, background, rect, indent, color, units): + self.background = background + self.rect = rect + self.icons = [] + x = rect.left + indent + base = get_color_swapped_surface( + load(self.get_resource("HUD_circle.png")).convert_alpha(), + (0, 0, 0), color) + while x <= self.rect.right - base.get_width() - self.SPACING: + icon = Sprite(self) + icon.add_frame(base) + icon.location.midleft = x, self.rect.centery + self.icons.append(icon) + x += icon.location.w + self.SPACING + self.units = units + + def reset(self): + self.amount = self.units + for icon in self.icons: + icon.unhide() + + def change(self, delta): + self.amount += delta + cutoff = float(self.amount) / self.units * len(self.icons) + for ii, icon in enumerate(self.icons): + if ii < cutoff: + icon.unhide() + else: + icon.hide() + + def update(self): + ds = self.get_display_surface() + ds.blit(self.background, self.rect) + for icon in self.icons: + icon.update() + + class Title(GameChild): def __init__(self, parent): @@ -1010,11 +1054,13 @@ class Chemtrails(Sprite): for direction in (NS.N, NS.NE, NS.E, NS.NW, NS.S, NS.W): self.add_frameset([direction], switch=(direction == NS.N)) self.life = Life(self) + self.boys = Boys(self) self.timer = Timer(self) def reset(self): self.deactivate() self.life.reset() + self.boys.reset() self.timer.reset() def deactivate(self): @@ -1036,13 +1082,15 @@ class Chemtrails(Sprite): if boss.queue: self.timer.tick() self.attack() - if self.timer.time_remaining < 0: + if self.timer.amount < 0: self.life.decrease() if not boss.is_playing(boss.show_end_dialogue): self.timer.reset() boss.combo() - # self.timer.update() - self.life.update() + if not boss.is_playing(boss.show_introduction_dialogue): + self.timer.update() + self.life.update() + self.boys.update() def attack(self): boss = self.get_game().boss @@ -1103,94 +1151,52 @@ class Chemtrails(Sprite): self.orientation = None -class Timer(GameChild): - - TEXT = u"\u25F7" - BAR_POSITION = 448, 11 - SIZE = 160 - TOP = 120 - RING_OFFSET = 8 +class Timer(Meter): def __init__(self, parent): - GameChild.__init__(self, parent) - self.background = Sprite(self) - image = load(self.get_resource("HUD_background.png")).convert_alpha() - image = flip(image, True, False) - self.background.add_frame(image) - self.background.location.topright = self.get_display_surface().get_rect().topright - self.bar = load(self.get_resource("HUD_bar.png")).convert_alpha() - self.bar = flip(self.bar, True, False) - self.hourglass = Sprite(self) - self.hourglass.load_from_path(self.get_resource("Hourglass.png"), True) + Meter.__init__(self, parent) dsr = self.get_display_surface().get_rect() - self.hourglass.location.midright = dsr.right, self.TOP + self.SIZE / 2 - - def reset(self): - self.time_remaining = self.get_configuration("time", "timer-start-time") + background = load(self.get_resource("HUD_timer.png")).convert() + rect = background.get_rect() + rect.bottomright = dsr.right - 6, dsr.bottom - 4 + self.setup(background, rect, 53, (0, 0, 255), + self.get_configuration("time", "timer-start-time")) def add_time(self, amount): - self.time_remaining += amount + self.change(amount) def tick(self): - self.time_remaining -= self.get_game().time_filter.get_last_frame_duration() - - def update(self): - self.hourglass.update() - if self.time_remaining > 5500: - hue = 120 - elif self.time_remaining > 3000: - hue = 30 - else: - hue = 0 - ds = self.get_display_surface() - max_time = self.get_configuration("time", "timer-max-time") - remaining_ratio = float(self.time_remaining) / max_time - left = ds.get_width() - self.SIZE / 2 - ds.blit(self.get_ring(get_hsla_color(hue, lightness=20, alpha=67), remaining_ratio), - (left, self.TOP + self.RING_OFFSET)) - ds.blit(self.get_ring(get_hsla_color(hue, lightness=80, alpha=67), remaining_ratio), - (left, self.TOP - self.RING_OFFSET)) - ds.blit(self.get_ring(get_hsla_color(hue, alpha=67), remaining_ratio), (left, self.TOP)) - - def get_ring(self, color, remaining): - image = Image.new("RGBA", (self.SIZE, self.SIZE)) - draw = ImageDraw.Draw(image) - draw.pieslice((0, 0, self.SIZE - 1, self.SIZE - 1), 90, remaining * 180 + 90, - fill=(color.r, color.g, color.b, color.a)) - draw.ellipse((self.SIZE / 4, self.SIZE / 4, self.SIZE / 4 * 3, self.SIZE / 4 * 3), (0, 0, 0, 0)) - string = fromstring(image.tobytes(), image.size, image.mode) - image.close() - return string + self.change(-self.get_game().time_filter.get_last_frame_duration()) -class Life(GameChild): - - SPACING = 30 - MARGIN = 0 +class Life(Meter): def __init__(self, parent): - GameChild.__init__(self, parent) - self.heart = load(self.get_resource("Heart.png")).convert_alpha() - - def reset(self): - self.count = 3 + Meter.__init__(self, parent) + dsr = self.get_display_surface().get_rect() + background = load(self.get_resource("HUD_health.png")).convert() + rect = background.get_rect() + rect.bottomleft = 172, dsr.bottom - 4 + self.setup(background, rect, 70, (255, 0, 0), 3) def decrease(self): self.get_game().sfx["hurt"].play() - if self.count > 0: - self.count -= 1 - if self.count <= 0: - self.count = 0 + self.change(-1) + if self.amount <= 0: + self.amount = 0 + self.parent.boys.change(-1) self.get_game().boss.finish_battle(False) - def update(self): - ds = self.get_display_surface() - dsr = ds.get_rect() - hr = self.heart.get_rect() - rect = Rect(0, 0, hr.w * self.count + self.SPACING * (self.count - 1), hr.h) - rect.midbottom = dsr.centerx, dsr.h - self.MARGIN - for x in xrange(rect.left, rect.right, hr.w + self.SPACING): - ds.blit(self.heart, (x, rect.top)) + +class Boys(Meter): + + def __init__(self, parent): + Meter.__init__(self, parent) + dsr = self.get_display_surface().get_rect() + background = load(self.get_resource("HUD_lives.png")).convert() + rect = background.get_rect() + rect.bottomleft = 6, dsr.bottom - 4 + self.setup(background, rect, 60, (0, 255, 0), 3) class Boss(Animation): @@ -1227,7 +1233,7 @@ class Boss(Animation): self.spoopy.set_frameset("normal") def start_level(self, index): - self.level_index = 2 + self.level_index = index self.battle_finished = False self.player_defeated = False self.health.reset() @@ -1669,34 +1675,20 @@ class Sword(Animation): sprite.update(substitute=substitute) -class Health(GameChild): +class Health(Meter): - TEXT = "BOSS" - BAR_POSITION = 23, 11 - BACKGROUND_ALPHA = 125 - OFFSET = 11 + OFFSET = 4 def __init__(self, parent): - GameChild.__init__(self, parent) - self.background = Sprite(self) - self.background.load_from_path(self.get_resource("HUD_boss_health_background.png"), True) + Meter.__init__(self, parent) dsr = self.get_display_surface().get_rect() - self.background.location.center = dsr.centerx, self.OFFSET - self.foreground = Sprite(self) - self.foreground.load_from_path(self.get_resource("HUD_boss_health_foreground.png"), True) - self.foreground.location.center = dsr.centerx, self.OFFSET - self.label = Sprite(self) - font = Font(self.get_resource("rounded-mplus-1m-bold.ttf"), 24) - text = font.render(self.TEXT, True, Color("white")) - self.label.add_frame(text) - self.label.location.topleft = 2, -2 - self.bar = load(self.get_resource("HUD_bar.png")).convert_alpha() - - def reset(self): - self.amount = 100 + background = load(self.get_resource("HUD_boss.png")).convert() + rect = background.get_rect() + rect.midtop = dsr.centerx, self.OFFSET + self.setup(background, rect, 52, (255, 0, 255), 100) def decrease(self, damage): - self.amount -= damage + self.change(-damage) self.parent.damage() if self.amount <= 0: self.amount = 0 @@ -1706,22 +1698,6 @@ class Health(GameChild): else: self.parent.play(self.parent.cancel_flash, delay=1000, play_once=True) - def update(self): - self.background.update() - if self.amount > 50: - shift = 0 - elif self.amount > 25: - shift = -70 - else: - shift = -120 - ratio = self.amount / 100.0 - ds = self.get_display_surface() - ds.set_clip((self.foreground.location.left, self.foreground.location.top, - int(self.foreground.location.w * ratio), self.foreground.location.h)) - surface = get_hue_shifted_surface(self.foreground.get_current_frame(), shift) - ds.blit(surface, self.foreground.location.topleft) - ds.set_clip(None) - class Ending(Animation): diff --git a/resource/HUD_boss.png b/resource/HUD_boss.png new file mode 100644 index 0000000..02a1063 Binary files /dev/null and b/resource/HUD_boss.png differ diff --git a/resource/HUD_circle.png b/resource/HUD_circle.png new file mode 100644 index 0000000..a99fdf7 Binary files /dev/null and b/resource/HUD_circle.png differ diff --git a/resource/HUD_health.png b/resource/HUD_health.png new file mode 100644 index 0000000..8cb0922 Binary files /dev/null and b/resource/HUD_health.png differ diff --git a/resource/HUD_lives.png b/resource/HUD_lives.png new file mode 100644 index 0000000..3646a29 Binary files /dev/null and b/resource/HUD_lives.png differ diff --git a/resource/HUD_timer.png b/resource/HUD_timer.png new file mode 100644 index 0000000..4b89327 Binary files /dev/null and b/resource/HUD_timer.png differ diff --git a/resource/scores b/resource/scores index 2546f5f..d4c0f1d 100644 --- a/resource/scores +++ b/resource/scores @@ -15,7 +15,3 @@ 171204 256769 312561 -167744 -91410 -41874 -32477