diff --git a/config b/config index 724bd0c..707a6f1 100644 --- a/config +++ b/config @@ -11,19 +11,23 @@ package-root = electric_sieve init-script = electric-sieve [display] -caption = Electric Sieve +caption = iBITFIT #dimensions = 420, 700 dimensions = 480, 720 score-font-path = font/Titan-One.ttf title-font-path = font/Oxygen.ttf -scoreboard-font-path = font/terminus/Terminus.ttf +scoreboard-font-path = font/terminus/Terminus-Bold.ttf initials-font = font/terminus/Terminus-Bold.ttf -show-framerate = yes +show-framerate = no rotate = no [mouse] visible = no +[input] +title-hold = 2000 +initials-hold = 1000 + [keys] quit = K_ESCAPE advance = K_RETURN @@ -39,6 +43,7 @@ path = high-scores [audio] title = aud/Meld.ogg title-advance = aud/It.wav +title-fade = 30000 triangles = aud/777.ogg hit = aud/Skinball.wav miss = aud/0Sj-99_Em.wav diff --git a/electric_sieve/ElectricSieve.py b/electric_sieve/ElectricSieve.py index b42e93e..4eb5304 100644 --- a/electric_sieve/ElectricSieve.py +++ b/electric_sieve/ElectricSieve.py @@ -14,7 +14,7 @@ from pygame.locals import * from lib.pgfw.pgfw.Game import Game from lib.pgfw.pgfw.GameChild import GameChild -from lib.pgfw.pgfw.Sprite import Sprite +from lib.pgfw.pgfw.Sprite import Sprite, BlinkingSprite from lib.pgfw.pgfw.Vector import Vector from lib.pgfw.pgfw.extension import render_box @@ -47,6 +47,14 @@ class ElectricSieve(Game): { "bool": "rotate" }, + "input": + { + "int": ["title-hold", "initials-hold"] + }, + "audio": + { + "int": "title-fade" + }, "land": { "int": ["gradient", "height", "x-step"], @@ -163,35 +171,35 @@ class ElectricSieve(Game): return rotated def update(self): - self.title.update() - # Test if the level is being played if self.triangles.active: # Draw grid effect self.land.update() - # Set the background alpha low to create a trail effect on the triangles. - #self.background.set_alpha(255 * 0.1) - - # Draw the alpha background only to the trail effect surface. This will partially erase the previous drawings of the triangles. - #self.trail_effect.blit(self.background, (0, 0)) - # Draw triangles onto the trail effect surface, update position self.triangles.update() - # Set alpha back to full for drawing the bottom layer background - #self.background.set_alpha(255) - self.get_display_surface().blit(self.background, (0, 0)) + if not self.title.active: + # Draw bottom layer background + self.get_display_surface().blit(self.background, (0, 0)) + + # Draw static behind objects on title screen + if self.title.active: + self.static.update() # Draw the triangles to the screen, using the intermediate trail effect surface self.get_display_surface().blit(self.trail_effect, (0, 0)) + self.title.update() + # Draw the sieve self.sieve.update() - # Draw the static - self.static.update() + if not self.title.active: + + # Draw the static + self.static.update() class Title(GameChild): @@ -232,6 +240,13 @@ class Title(GameChild): # cx = self.display_surface.get_rect().centerx # captions[0].location.center = cx, 301 # captions[1].location.center = cx, 398 + self.button_prompt = BlinkingSprite(self, 500) + font = pygame.font.Font(self.get_resource("terminus/Terminus.ttf"), 32) + self.button_prompt.add_frame(self.get_game().orient(font.render("HOLD LEFT OR RIGHT TO PLAY", True, pygame.Color(0, 0, 0), pygame.Color(255, 255, 255)))) + if not self.get_game().rotated: + self.button_prompt.location.midbottom = self.get_display_surface().get_rect().midbottom + else: + self.button_prompt.location.midright = self.get_display_surface().get_rect().midright self.scoreboard = Scoreboard(self) self.music = Sound(self.get_resource("audio", "title")) self.advance = Sound(self.get_resource("audio", "title-advance")) @@ -239,17 +254,27 @@ class Title(GameChild): def respond(self, event): if self.active: - if self.delegate.compare(event, "advance"): - self.deactivate() - self.parent.triangles.activate() - self.parent.sieve.activate() - self.parent.static.activate() - self.advance.play() - self.get_display_surface().blit(self.get_game().background, (0, 0)) + self.idle_time = 0 + if not self.music.get_num_channels(): + self.music.play(-1, 0, 1000) + self.get_game().static.noise.fadeout(1000) + if self.delegate.compare(event, "left", cancel=False) or self.delegate.compare(event, "right", cancel=False): + self.holding_button = True + elif self.delegate.compare(event, "left", cancel=True) or self.delegate.compare(event, "right", cancel=True): + self.holding_button = False + self.holding_button_elapsed = 0 def activate(self): self.active = True + self.holding_button = False + self.holding_button_elapsed = 0 + self.idle_time = 0 self.music.play(-1) + self.get_game().static.activate() + self.get_game().static.full() + self.get_game().static.noise.stop() + self.get_game().sieve.activate() + self.get_game().triangles.activate(music=False) def deactivate(self): self.active = False @@ -257,10 +282,39 @@ class Title(GameChild): def update(self): if self.active: - self.display_surface.blit(self.background, (0, 0)) - # for caption in self.captions: - # caption.update() - self.scoreboard.update() + if self.holding_button_elapsed > self.get_configuration("input", "title-hold"): + self.deactivate() + self.parent.triangles.reset() + while self.parent.triangles: + self.parent.triangles.pop() + self.parent.triangles.activate() + self.parent.sieve.activate() + self.parent.static.reset() + self.parent.static.activate() + self.advance.play() + self.get_game().trail_effect.fill(Color(0, 0, 0, 0)) + self.get_display_surface().blit(self.get_game().background, (0, 0)) + else: + if self.idle_time > self.get_configuration("audio", "title-fade"): + self.music.fadeout(5000) + if not self.get_game().static.noise.get_num_channels(): + self.get_game().static.noise.set_volume(0.25) + self.get_game().static.noise.play(-1, 0, 5000) + else: + self.idle_time += self.get_game().time_filter.get_last_frame_duration() + if self.holding_button: + self.holding_button_elapsed += self.get_game().time_filter.get_last_frame_duration() + logo = Sprite(self) + font = pygame.font.Font(self.get_resource("terminus/TerminusItalic.ttf"), + 62 + int(self.holding_button_elapsed / self.get_configuration("input", "title-hold") * 72)) + logo.add_frame(self.get_game().orient(font.render("iBITFIT", True, pygame.Color(0, 0, 0), pygame.Color(255, 255, 255)))) + if not self.get_game().rotated: + logo.location.midtop = self.get_display_surface().get_rect().midtop + else: + logo.location.midleft = self.get_display_surface().get_rect().midleft + logo.update() + self.button_prompt.update() + self.scoreboard.update() class Strip(Sprite): @@ -346,12 +400,13 @@ class Scoreboard(GameChild): BACKGROUND = 255, 255, 255 FOREGROUND = 27, 27, 27 NEW = 27, 27, 27 - SPACING = 70 - MARGIN = 30 + SPACING = 45 + MARGIN = 0 BLINK_INTERVAL = 400 - PADDING = 6 + PADDING = 0 BORDER = 1 - SCORE_COUNT = 9 + SCORE_COUNT = 11 + SIZES = [32, 28, 24, 22, 22, 20, 20, 20, 18, 18, 18] def __init__(self, parent): GameChild.__init__(self, parent) @@ -363,41 +418,39 @@ class Scoreboard(GameChild): def load(self): self.sprites = sprites = [] font_path = self.get_resource("display", "scoreboard-font-path") - sizes = [24] * self.SCORE_COUNT blink = False - for ii, score in enumerate(self.get_scores()[:len(sizes)]): - font = Font(font_path, sizes[ii]) - sprites.append((Sprite(self, self.BLINK_INTERVAL), - Sprite(self, self.BLINK_INTERVAL))) + for ii, score in enumerate(self.get_scores()[:len(self.SIZES)]): + font = Font(font_path, self.SIZES[ii]) + sprites.append((Sprite(self, self.BLINK_INTERVAL), Sprite(self, self.BLINK_INTERVAL))) score_text = str(score[1]) - color = self.BACKGROUND if (self.most_recent_score and not blink and score[1:] == \ - self.most_recent_score) else self.FOREGROUND + color = self.BACKGROUND if (self.most_recent_score and not blink and score[1:] == self.most_recent_score) else self.FOREGROUND score_plate = font.render(score_text, False, color, self.BACKGROUND) rect = score_plate.get_rect() surface = Surface(rect.inflate((2, 2)).size) surface.fill(self.FOREGROUND) rect.center = surface.get_rect().center surface.blit(score_plate, rect) + width = 80 sprites[ii][1].add_frame(self.get_game().orient( - render_box(font, score_text, False, color, self.BACKGROUND, self.FOREGROUND, self.BORDER, self.PADDING))) + render_box(font, score_text, True, color, self.BACKGROUND, (0, 0, 0), padding=self.PADDING, width=width))) sprites[ii][0].add_frame(self.get_game().orient( - render_box(font, score[2], False, color, self.BACKGROUND, self.FOREGROUND, self.BORDER, self.PADDING))) + render_box(font, score[2], True, color, self.BACKGROUND, (0, 0, 0), padding=self.PADDING, width=width))) if self.most_recent_score and not blink and score[1:] == self.most_recent_score: sprites[ii][1].add_frame(self.get_game().orient( - render_box(font, score_text, False, self.NEW, self.BACKGROUND, self.FOREGROUND, self.BORDER, self.PADDING))) + render_box(font, score_text, True, self.NEW, self.BACKGROUND, (0, 0, 0), padding=self.PADDING, width=width))) sprites[ii][0].add_frame(self.get_game().orient( - render_box(font, score[2], False, self.NEW, self.BACKGROUND, self.FOREGROUND, self.BORDER, self.PADDING))) + render_box(font, score[2], True, self.NEW, self.BACKGROUND, (0, 0, 0), padding=self.PADDING, width=width))) blink = True if not self.get_game().rotated: sprites[ii][0].location.left = self.MARGIN sprites[ii][1].location.right = self.get_display_surface().get_rect().right - self.MARGIN - y = self.get_display_surface().get_rect().centery + self.SPACING * (ii - len(sizes) / 2) + y = self.get_display_surface().get_rect().centery + self.SPACING * (ii - len(self.SIZES) / 2) for sprite in sprites[ii]: sprite.location.centery = y else: sprites[ii][0].location.bottom = self.get_display_surface().get_height() - self.MARGIN sprites[ii][1].location.top = self.MARGIN - x = self.get_display_surface().get_rect().centerx + self.SPACING * (ii - len(sizes) / 2) + x = self.get_display_surface().get_rect().centerx + self.SPACING * (ii - len(self.SIZES) / 2) for sprite in sprites[ii]: sprite.location.centerx = x @@ -588,9 +641,10 @@ class Triangles(GameChild, list): def get_boost(self): return self.booster.get_change() - def activate(self): + def activate(self, music=True): self.active = True - self.music.play(-1, 0, 500) + if music: + self.music.play(-1, 0, 500) def update(self): if self.active: @@ -600,9 +654,10 @@ class Triangles(GameChild, list): sieve = self.parent.sieve removed = False if self[0].location.colliderect(sieve.electric.location): - self.parent.acid.increase() - self.streak += 1 - self.score += self.streak ** .8 + self.parent.acid.get_volume() * 5 + self[0].count + if not self.get_game().title.active: + self.parent.acid.increase() + self.streak += 1 + self.score += self.streak ** .8 + self.parent.acid.get_volume() * 5 + self[0].count self.remove(self[0]) self.hit.play() removed = True @@ -614,9 +669,10 @@ class Triangles(GameChild, list): br_offset = (sieve.location.left, 0) if not self.get_game().rotated else \ (0, sieve.location.bottom - self.get_display_surface().get_height()) if tr.move(tr_offset).colliderect(br.move(br_offset)): + if not self.get_game().title.active: + self.parent.static.increase() + self.streak = 0 self.remove(self[0]) - self.parent.static.increase() - self.streak = 0 self.miss.play() removed = True break @@ -768,13 +824,14 @@ class Static(Sprite): def respond(self, event): if self.active and self.complete and not self.initials.active: - if self.delegate.compare(event, "advance"): - if self.get_game().triangles.score > \ - self.get_game().title.scoreboard.get_scores()[Scoreboard.SCORE_COUNT - 1][1]: + if self.delegate.compare(event, "left") or self.delegate.compare(event, "right"): + if self.get_game().triangles.score > self.get_game().title.scoreboard.get_scores()[Scoreboard.SCORE_COUNT - 1][1]: self.total.deactivate() self.initials.activate() else: self.finish(wipe=True) + self.get_delegate().cancel_propagation() + self.get_game().suppress_input_temporarily(500) def finish(self, text="---", wipe=False): if wipe: @@ -796,26 +853,30 @@ class Static(Sprite): if self.increaser.time >= self.increaser.nodeset[-1].x + 5000: self.increaser.time = self.increaser.nodeset[-1].x + 5000 + def full(self): + self.intensity = 1 + def activate(self): self.active = True self.noise.play(-1) def update(self): if self.active: - if not self.complete and self.intensity >= .65: - self.complete = True - self.parent.sieve.deactivate() - self.parent.triangles.deactivate() - self.set_alpha(255) - self.noise.fadeout(6000) - self.end.play(-1, 0, 4000) - self.total.load() - elif not self.complete: - self.set_alpha(min(150, int(self.intensity * 1.15 * 255))) - if self.intensity > 0: - self.intensity *= .998 - self.increaser.update() - self.noise.set_volume(self.intensity) + if not self.get_game().title.active: + if not self.complete and self.intensity >= .65: + self.complete = True + self.parent.sieve.deactivate() + self.parent.triangles.deactivate() + self.set_alpha(255) + self.noise.fadeout(6000) + self.end.play(-1, 0, 4000) + self.total.load() + elif not self.complete: + self.set_alpha(min(150, int(self.intensity * 1.15 * 255))) + if self.intensity > 0: + self.intensity *= .998 + self.increaser.update() + self.noise.set_volume(self.intensity) if self.intensity > .1: Sprite.update(self) self.total.update() @@ -828,11 +889,18 @@ class Initials(GameChild): FOREGROUND = 27, 27, 27 BACKGROUND = 255, 255, 255 PADDING = 10 - ARROW_MARGIN = 40 + ARROW_MARGIN = 20 ARROW_HEIGHT = 10 def __init__(self, parent): GameChild.__init__(self, parent) + self.button_prompt = BlinkingSprite(self, 500) + font = pygame.font.Font(self.get_resource("terminus/Terminus.ttf"), 32) + self.button_prompt.add_frame(self.get_game().orient(font.render("HOLD RIGHT TO ENTER", True, pygame.Color(0, 0, 0), pygame.Color(255, 255, 255)))) + if not self.get_game().rotated: + self.button_prompt.location.midbottom = self.get_display_surface().get_rect().midbottom + else: + self.button_prompt.location.midright = self.get_display_surface().get_rect().midright self.reset() self.deactivate() self.font = Font(self.get_resource("display", "initials-font"), self.LETTER_SIZE) @@ -841,6 +909,8 @@ class Initials(GameChild): def reset(self): self.text = "---" self.index = 0 + self.holding_button = False + self.holding_button_elapsed = 0 def deactivate(self): self.active = False @@ -848,21 +918,15 @@ class Initials(GameChild): def respond(self, event): if self.active: compare = self.get_game().delegate.compare - if compare(event, "right") or compare(event, "advance"): - self.index += 1 - if self.index == len(self.text): - self.index = 0 - if compare(event, "advance"): - self.deactivate() - self.parent.finish(self.text) - elif compare(event, "left"): - self.index -= 1 - if self.index == -1: - self.index = len(self.text) - 1 - elif compare(event, "up") or compare(event, "down"): - if compare(event, "up"): + if compare(event, "right", cancel=False): + self.holding_button = True + elif compare(event, "right", cancel=True): + self.holding_button = False + self.holding_button_elapsed = 0 + if compare(event, "right", cancel=True) or compare(event, "left", cancel=True): + if compare(event, "right", cancel=True): increment = 1 - elif compare(event, "down"): + elif compare(event, "left", cancel=True): increment = -1 letter = self.text[self.index] if letter == '-': @@ -885,6 +949,19 @@ class Initials(GameChild): def update(self): if self.active: ds = self.get_display_surface() + self.button_prompt.update() + if self.holding_button: + self.holding_button_elapsed += self.get_game().time_filter.get_last_frame_duration() + if self.holding_button_elapsed > self.get_configuration("input", "initials-hold"): + self.index += 1 + if self.index == len(self.text): + self.deactivate() + self.parent.finish(self.text) + self.reset() + else: + self.holding_button = False + self.holding_button_elapsed = 0 + self.get_game().suppress_input_temporarily(500) for ii, letter in enumerate(self.text): box = self.get_game().orient(render_box( self.font, letter, False, self.FOREGROUND, self.BACKGROUND, self.FOREGROUND, padding=self.PADDING)) @@ -897,16 +974,19 @@ class Initials(GameChild): rect.centery = (len(self.text) - 1 - ii) * ds.get_height() / 3 + ds.get_height() / 6 ds.blit(box, rect) if ii == self.index: + hold_offset = self.holding_button_elapsed / self.get_configuration("input", "initials-hold") * 10 if not self.get_game().rotated: - margin = self.ARROW_MARGIN + x = rect.left - self.ARROW_MARGIN + left_points = ((x, rect.top), (x, rect.bottom), (x - self.ARROW_HEIGHT, rect.centery)) + x = rect.right + self.ARROW_MARGIN + hold_offset + right_points = ((x, rect.top), (x, rect.bottom), (x + self.ARROW_HEIGHT, rect.centery)) else: - margin = self.ARROW_MARGIN // 2 - polygon(ds, (0, 255, 0), ((rect.left, rect.top - margin), - (rect.right, rect.top - margin), - (rect.centerx, rect.top - margin - self.ARROW_HEIGHT))) - polygon(ds, (0, 255, 0), ((rect.left, rect.bottom + margin), - (rect.right, rect.bottom + margin), - (rect.centerx, rect.bottom + margin + self.ARROW_HEIGHT))) + y = rect.top - self.ARROW_MARGIN - hold_offset + left_points = ((rect.left, y), (rect.right, y), (rect.centerx, y - self.ARROW_HEIGHT)) + y = rect.bottom + self.ARROW_MARGIN + right_points = ((rect.left, y), (rect.right, y), (rect.centerx, y + self.ARROW_HEIGHT)) + pygame.draw.polygon(ds, pygame.Color(0, 0, 0), left_points) + pygame.draw.polygon(ds, pygame.Color(0, 0, 0), right_points) class Total(Sprite): diff --git a/resource/high-scores b/resource/high-scores index ed21b33..d8cf821 100644 --- a/resource/high-scores +++ b/resource/high-scores @@ -1,3 +1,5 @@ +1398631170.296798 140 FIT +1398631170.296798 100 FIT 1398631170.296798 80 FIT 1398631170.296798 60 FIT 1398631170.296798 50 FIT @@ -7,4 +9,3 @@ 1398635792.99 20 FIT 1398635792.99 15 FIT 1398635792.99 10 FIT -1672460647.69491 211 ---