diff --git a/NS.py b/NS.py index f748b56..ef72eab 100644 --- a/NS.py +++ b/NS.py @@ -3,8 +3,11 @@ from random import randint, choice from math import pi from copy import copy +from glob import iglob +from os.path import basename from pygame import Surface, Color +from pygame.event import clear from pygame.mixer import Sound from pygame.image import load from pygame.transform import rotate, flip @@ -47,7 +50,7 @@ class SoundEffect(GameChild, Sound): class NS(Game, Animation): LNW, LNE, LSE, LSW = range(4) - N, E, S, W, NE, NW = range(6) + N, NE, E, NW, S, W = range(6) FRONT_WIDTH = 230 BACK_WIDTH = 500 LENGTH = 150 @@ -57,6 +60,7 @@ class NS(Game, Animation): def __init__(self): Game.__init__(self) Animation.__init__(self, self) + self.load_sfx() self.subscribe(self.respond, KEYDOWN) self.subscribe(self.respond, KEYUP) self.subscribe(self.respond) @@ -72,6 +76,12 @@ class NS(Game, Animation): self.boss = Boss(self) self.last_press = get_ticks() self.reset() + clear() + + def load_sfx(self): + sfx = self.sfx = {} + for path in iglob(self.get_resource("sfx/") + "*.wav"): + sfx[basename(path.split(".")[0])] = SoundEffect(self, path) def reset(self, leave_wipe_running=False): self.suppressing_input = False @@ -146,6 +156,7 @@ class Title(GameChild): self.text.add_frameset([1], name="half") self.text.location.center = dsr.centerx, dsr.bottom - 100 self.angle = choice((pi / 4, 3 * pi / 4, 5 * pi / 4, 7 * pi / 4)) + self.button_sound = self.get_game().sfx["button"] def reset(self): self.activate() @@ -189,9 +200,11 @@ class Title(GameChild): self.first_pressed = True self.first_pressed_elapsed = 0 self.text.set_frameset("half") + self.button_sound.play() elif not wipe.is_playing() and self.first_pressed and \ self.get_game().platform.get_edge_pressed() == NS.NW: wipe.start(self.activate_introduction) + self.get_game().sfx["confirm"].play() elif self.first_pressed: self.first_pressed_elapsed += self.get_game().time_filter.get_last_frame_duration() if self.first_pressed_elapsed > 4000: @@ -211,7 +224,7 @@ class Dialogue(Animation): FONT_SIZE = 18 def __init__(self, parent): - Animation.__init__(self, parent, interval=70) + Animation.__init__(self, parent) ds = self.get_display_surface() dsr = ds.get_rect() frame = Surface((640, 72)) @@ -259,14 +272,16 @@ class Dialogue(Animation): def show_text(self, text): self.full_text = text self.text_index = 0 + self.speech_channel = self.get_game().sfx["talk"].play(-1) self.play() def build_frame(self): - self.text_index += 1 - if self.text_index == len(self.full_text): - self.halt() + self.text_index += 2 + if self.text_index >= len(self.full_text): + self.show_all() def show_all(self): + self.speech_channel.stop() self.text_index = len(self.full_text) self.halt() @@ -358,6 +373,7 @@ class Introduction(Animation): if self.skateboard.location.colliderect(self.slime_bag.location.inflate(-30, -30)): self.halt(self.move_board) self.play(self.take_board, delay=2000, play_once=True) + self.get_game().sfx["go"].play() def take_board(self): self.skateboard.hide() @@ -405,6 +421,7 @@ class Introduction(Animation): platform = self.get_game().platform if platform.get_edge_pressed() == self.TUTORIAL_MOVES[self.tutorial_index]: self.tutorial_index += 1 + self.get_game().sfx["land"].play() if self.tutorial_index == len(self.TUTORIAL_MOVES): self.text_index += 1 self.advance_prompt.cancel_first_press() @@ -433,6 +450,7 @@ class SkipPrompt(Sprite): for ii in xrange(3): self.load_from_path(self.get_resource("Skip_%i.png" % ii), True) self.add_frameset([ii]) + self.button_sound = self.get_game().sfx["button"] def reset(self): self.press_index = 0 @@ -444,11 +462,14 @@ class SkipPrompt(Sprite): if self.press_index == 0 and platform.get_edge_pressed() == NS.S: self.press_index += 1 self.set_frameset(2) + self.button_sound.play() elif self.press_index == 1 and platform.get_edge_pressed() == NS.NE: self.press_index += 1 self.set_frameset(3) + self.button_sound.play() elif self.press_index == 2 and platform.get_edge_pressed() == NS.W: self.callback() + self.get_game().sfx["confirm"].play() elif self.press_index > 0: self.press_elapsed += self.get_game().time_filter.get_last_frame_duration() if self.press_elapsed > 4000: @@ -483,9 +504,13 @@ class AdvancePrompt(Sprite): def press_first(self): self.first_pressed = True self.set_frameset("half") + self.get_game().sfx["button"].play() def check_second_press(self): - return self.first_pressed and self.get_game().platform.get_edge_pressed() == NS.NW + pressed = self.first_pressed and self.get_game().platform.get_edge_pressed() == NS.NW + if pressed: + self.get_game().sfx["confirm"].play() + return pressed def update(self): if self.first_pressed: @@ -505,6 +530,7 @@ class Wipe(Animation): Animation.__init__(self, parent) self.image = load(self.get_resource("Ink.png")).convert() self.image.set_colorkey(self.TRANSPARENT_COLOR) + self.sound = self.get_game().sfx["wipe"] def reset(self): self.deactivate() @@ -519,10 +545,11 @@ class Wipe(Animation): def start(self, callback): self.activate() self.up = True - self.get_game().suppress_input() + # self.get_game().suppress_input() self.blind_height = self.get_display_surface().get_height() / self.BLIND_COUNT self.callback = callback self.play() + self.sound.play() def build_frame(self): if self.up: @@ -759,14 +786,15 @@ class Light(Animation): return orientation in (NS.S, NS.NE, NS.W) -class Chemtrails(GameChild): +class Chemtrails(Sprite): - TIME_LIMIT = 8000 TIME_ADDITION = 1000 def __init__(self, parent): - GameChild.__init__(self, parent) - self.image = load(self.get_resource("Chemtrails.png")).convert_alpha() + Sprite.__init__(self, parent) + self.load_from_path(self.get_resource("littleSlimeGoop"), True) + 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.timer = Timer(self) @@ -788,6 +816,7 @@ class Chemtrails(GameChild): def update(self): if self.active: self.orient() + Sprite.update(self) if not self.get_game().introduction.active: boss = self.get_game().boss if boss.queue: @@ -818,50 +847,42 @@ class Chemtrails(GameChild): self.timer.reset() if not boss.is_playing(boss.show_end_dialogue): boss.combo() + self.get_game().sfx["complete_pattern"].play() + else: + self.get_game().sfx["land"].play() self.get_game().platform.reset_lights() def orient(self): ds = self.get_display_surface() edge = self.get_game().platform.get_edge_pressed() dy = -Light.INTRODUCTION_OFFSET if self.get_game().introduction.active else 0 + if edge is not None: + self.set_frameset(edge + 1) + self.unhide() + else: + self.hide() if edge == NS.N: - rect = self.image.get_rect() - rect.center = ds.get_width() / 2, NS.FRONT - 30 + dy - ds.blit(self.image, rect.topleft) + self.location.center = ds.get_width() / 2, NS.FRONT + 15 + dy self.orientation = NS.N elif edge == NS.E: - image = rotate(self.image, 270) - rect = image.get_rect() - rect.center = ds.get_width() / 2 + NS.FRONT_WIDTH / 2, \ - NS.FRONT + NS.LENGTH * NS.STEP + 10 + dy - ds.blit(image, rect.topleft) + self.location.center = ds.get_width() / 2 + NS.FRONT_WIDTH / 2 - 115, \ + NS.FRONT + NS.LENGTH * NS.STEP - 75 + dy self.orientation = NS.E elif edge == NS.S: - rect = self.image.get_rect() - rect.center = ds.get_width() / 2, \ - NS.FRONT + NS.LENGTH - NS.LENGTH * NS.STEP - 20 + dy - ds.blit(self.image, rect.topleft) + self.location.center = ds.get_width() / 2, \ + NS.FRONT + NS.LENGTH - NS.LENGTH * NS.STEP - 110 + dy self.orientation = NS.S elif edge == NS.W: - image = rotate(self.image, 270) - rect = image.get_rect() - rect.center = ds.get_width() / 2 - NS.FRONT_WIDTH / 2 + 70, \ - NS.FRONT + NS.LENGTH * NS.STEP + 10 + dy - ds.blit(image, rect.topleft) + self.location.center = ds.get_width() / 2 - NS.FRONT_WIDTH / 2 + 100, \ + NS.FRONT + NS.LENGTH * NS.STEP - 85 + dy self.orientation = NS.W elif edge == NS.NW: - image = rotate(self.image, 315) - rect = image.get_rect() - rect.center = ds.get_width() / 2 + 45, \ - NS.FRONT + NS.LENGTH * NS.STEP - 40 + dy - ds.blit(image, rect.topleft) + self.location.center = ds.get_width() / 2 + 5, \ + NS.FRONT + NS.LENGTH * NS.STEP - 75 + dy self.orientation = NS.NW elif edge == NS.NE: - image = rotate(self.image, 45) - rect = image.get_rect() - rect.center = ds.get_width() / 2 - 30, \ - NS.FRONT + NS.LENGTH * NS.STEP - 50 + dy - ds.blit(image, rect.topleft) + self.location.center = ds.get_width() / 2 + 10, \ + NS.FRONT + NS.LENGTH * NS.STEP - 80 + dy self.orientation = NS.NE else: self.orientation = None @@ -871,8 +892,8 @@ class Timer(GameChild): TEXT = u"\u25F7" BAR_POSITION = 448, 11 - MAX_TIME = 9000 - START_TIME = 6000 + MAX_TIME = 10000 + START_TIME = 7000 def __init__(self, parent): GameChild.__init__(self, parent) @@ -928,6 +949,7 @@ class Life(GameChild): self.count = 3 def decrease(self): + self.get_game().sfx["hurt"].play() if self.count > 0: self.count -= 1 if self.count <= 0: @@ -1006,7 +1028,7 @@ class Boss(Animation): dialogue.activate() if self.level_index == 0: dialogue.show_text("You'll never be able to block my sword, you lizard slime!" + - " See if you\ncan keep up with these moves!") + " See\nif you can keep up with these moves!") elif self.level_index == 1: dialogue.show_text("We're just warming up, slime breath! Prepare to get spun" + " by\nthese combos!") @@ -1344,6 +1366,7 @@ class Sword(Sprite): else: self.set_frameset("rdiagonal") self.location.center = dsr.centerx, dsr.centery - 100 + self.get_game().sfx["brandish"].play() self.play(self.lower, delay=400, play_once=True) if len(self.parent.unbrandished) > 0: self.play(self.brandish, delay=600, play_once=True) @@ -1382,6 +1405,7 @@ class Health(GameChild): self.parent.damage() if self.amount <= 0: self.amount = 0 + self.get_game().sfx["defeat"].play() self.get_game().boss.finish_battle(True) else: self.parent.play(self.parent.cancel_flash, delay=1000, play_once=True) diff --git a/resource/littleSlimeGoop/0_back.png b/resource/littleSlimeGoop/0_back.png new file mode 100644 index 0000000..6dee82d Binary files /dev/null and b/resource/littleSlimeGoop/0_back.png differ diff --git a/resource/littleSlimeGoop/1_downRight.png b/resource/littleSlimeGoop/1_downRight.png new file mode 100644 index 0000000..6693e67 Binary files /dev/null and b/resource/littleSlimeGoop/1_downRight.png differ diff --git a/resource/littleSlimeGoop/2_right.png b/resource/littleSlimeGoop/2_right.png new file mode 100644 index 0000000..d6a8415 Binary files /dev/null and b/resource/littleSlimeGoop/2_right.png differ diff --git a/resource/littleSlimeGoop/3_downLeft.png b/resource/littleSlimeGoop/3_downLeft.png new file mode 100644 index 0000000..3489a1c Binary files /dev/null and b/resource/littleSlimeGoop/3_downLeft.png differ diff --git a/resource/littleSlimeGoop/4_front.png b/resource/littleSlimeGoop/4_front.png new file mode 100644 index 0000000..057dc96 Binary files /dev/null and b/resource/littleSlimeGoop/4_front.png differ diff --git a/resource/littleSlimeGoop/5_left.png b/resource/littleSlimeGoop/5_left.png new file mode 100644 index 0000000..6e22dc5 Binary files /dev/null and b/resource/littleSlimeGoop/5_left.png differ diff --git a/resource/sfx/brandish.wav b/resource/sfx/brandish.wav new file mode 100644 index 0000000..dae515b Binary files /dev/null and b/resource/sfx/brandish.wav differ diff --git a/resource/sfx/button.wav b/resource/sfx/button.wav new file mode 100644 index 0000000..99c3fd7 Binary files /dev/null and b/resource/sfx/button.wav differ diff --git a/resource/sfx/complete_pattern.wav b/resource/sfx/complete_pattern.wav new file mode 100644 index 0000000..78818e9 Binary files /dev/null and b/resource/sfx/complete_pattern.wav differ diff --git a/resource/sfx/confirm.wav b/resource/sfx/confirm.wav new file mode 100644 index 0000000..a3f8b6a Binary files /dev/null and b/resource/sfx/confirm.wav differ diff --git a/resource/sfx/defeat.wav b/resource/sfx/defeat.wav new file mode 100644 index 0000000..9c3b81f Binary files /dev/null and b/resource/sfx/defeat.wav differ diff --git a/resource/sfx/go.wav b/resource/sfx/go.wav new file mode 100644 index 0000000..864bc8a Binary files /dev/null and b/resource/sfx/go.wav differ diff --git a/resource/sfx/hurt.wav b/resource/sfx/hurt.wav new file mode 100644 index 0000000..8bb14dd Binary files /dev/null and b/resource/sfx/hurt.wav differ diff --git a/resource/sfx/land.wav b/resource/sfx/land.wav new file mode 100644 index 0000000..2a5bb44 Binary files /dev/null and b/resource/sfx/land.wav differ diff --git a/resource/sfx/talk.wav b/resource/sfx/talk.wav new file mode 100644 index 0000000..8dc1b26 Binary files /dev/null and b/resource/sfx/talk.wav differ diff --git a/resource/sfx/wipe.wav b/resource/sfx/wipe.wav new file mode 100644 index 0000000..ce8e7fb Binary files /dev/null and b/resource/sfx/wipe.wav differ