clock
authorFrank DeMarco <frank.s.demarco@gmail.com>
Sat, 28 Jun 2014 18:08:42 +0000 (03:08 +0900)
committerFrank DeMarco <frank.s.demarco@gmail.com>
Sat, 28 Jun 2014 18:08:42 +0000 (03:08 +0900)
config
hair_on_arm/HairOnArm.py

diff --git a/config b/config
index e41c0d3..63bde84 100644 (file)
--- a/config
+++ b/config
@@ -17,6 +17,8 @@ in = aud/cloud-meat-of-thigh/Raisin.ogg
 caster = aud/car-kicker/caster.ogg
 vertical = aud/car-kicker/menu-0.ogg
 horizontal = aud/car-kicker/toggle.ogg
+countdown = aud/car-kicker/countdown.ogg
+go = aud/car-kicker/go.ogg
 
 [image]
 gate = img/exenteration-of-canus/symplesiomorphic-metaglyph/
index ed1dd1e..78ada3b 100644 (file)
@@ -242,9 +242,11 @@ class Title(GameChild):
             self.menu.reset()
             self.activate()
 
-    def activate(self):
+    def activate(self, level_ii=None):
         self.active = True
         self.menu.activate()
+        if level_ii is not None:
+            self.menu.elements[0].active_value = level_ii
 
     def update(self):
         if self.active:
@@ -437,7 +439,11 @@ class Tour(Animation):
 
     def __init__(self, parent):
         Animation.__init__(self, parent)
+        self.display_surface = ds = self.get_display_surface()
         self.delegate = self.get_game().delegate
+        self.countdown_beep = SoundEffect(self, "countdown", .7)
+        self.go_beep = SoundEffect(self, "go", .7)
+        self.clock = Clock(self)
         self.ship = Ship(self)
         self.axes = Axes(self)
         self.static = Static(self)
@@ -445,24 +451,45 @@ class Tour(Animation):
         self.playing_drums.set_volume(.85)
         self.in_drums = Sound(self.get_resource("audio", "in"))
         self.in_drums.set_volume(.85)
+        self.game_over_surface = Surface(ds.get_size(), SRCALPHA)
+        self.game_over_surface.fill((0, 0, 0, 127))
+        font = Font(self.get_resource("display", "font"), 12)
+        self.game_over_text = font.render("G  A  M  E    O  V  E  R", True,
+                                          (255, 255, 0))
+        self.game_over_text_rect = self.game_over_text.get_rect()
+        self.game_over_text_rect.center = ds.get_rect().center
         self.subscribe(self.respond)
         self.register(self.fly_in, interval=100)
-        self.register(self.countdown, interval=100)
+        self.register(self.countdown, interval=1000)
         self.deactivate()
 
     def respond(self, event):
-        if self.delegate.compare(event, "reset-game"):
+        compare = self.delegate.compare
+        if compare(event, "reset-game"):
+            self.deactivate()
+        elif self.active and self.game_over and compare(event, "advance"):
             self.deactivate()
+            self.parent.title.activate(self.level_ii)
 
     def fly_in(self):
         if self.ship.move():
             self.halt(self.fly_in)
-            self.static.activate()
-            self.in_drums.fadeout(5000)
-            self.playing_drums.play(-1, 0, 5000)
+            self.play(self.countdown)
+            self.in_drums.fadeout(1000)
+            self.clock.activate()
 
     def countdown(self):
-        pass
+        if self.countdown_ii < 3:
+            self.clock.set_message_index(self.countdown_ii)
+            self.countdown_beep.play()
+            self.countdown_ii += 1
+        else:
+            self.halt(self.countdown)
+            self.go_beep.play()
+            self.axes.unsuppress()
+            self.clock.ticking = True
+            self.static.activate()
+            self.playing_drums.play(-1, 0, 5000)
 
     def deactivate(self):
         self.halt()
@@ -471,18 +498,22 @@ class Tour(Animation):
         self.static.fade_out(fade)
         self.playing_drums.fadeout(fade)
         self.in_drums.fadeout(fade)
+        self.ship.deactivate()
+        self.clock.deactivate()
 
     def activate(self, index):
         self.active = True
+        self.game_over = False
         self.start_level(index)
 
     def start_level(self, index):
+        self.level_ii = level_ii = index - 1
         self.nodes = nodes = []
         new = Node(self)
         while new.is_hidden():
             new = Node(self)
         nodes.append(new)
-        while len(nodes) < (3, 4, 5, 6, 8, 10, 12, 15, 18, 21)[index - 1]:
+        while len(nodes) < (3, 4, 5, 6, 8, 10, 12, 15, 18, 21)[level_ii]:
             new = Node(self)
             add = True
             for node in nodes:
@@ -492,15 +523,21 @@ class Tour(Animation):
                     break
             if add:
                 nodes.append(new)
+        self.axes.suppress()
         self.in_drums.play(-1, 0, 3000)
         self.ship.activate()
+        self.countdown_ii = 0
+        self.clock.deactivate()
         self.play(self.fly_in)
 
+    def end(self):
+        self.axes.suppress()
+        self.game_over = True
+
     def update(self):
         if self.active:
             Animation.update(self)
             self.static.update()
-            ds = self.get_display_surface()
             self.parent.sky.update()
             self.parent.floor.update()
             x, y, max_magnitude = self.axes.update()
@@ -511,6 +548,7 @@ class Tour(Animation):
             for node in sorted(self.nodes, key=lambda n: n.z):
                 if node.z >= 0 and not gate_drawn:
                     self.parent.gate.update()
+                    self.clock.update()
                     gate_drawn = True
                 node.update()
                 if self.ship.location[2] < node.z and not ship_drawn:
@@ -518,8 +556,108 @@ class Tour(Animation):
                     ship_drawn = True
             if not gate_drawn:
                 self.parent.gate.update()
+                self.clock.update()
             if not ship_drawn:
                 self.ship.update()
+            if self.game_over:
+                ds = self.display_surface
+                ds.blit(self.game_over_surface, (0, 0))
+                ds.blit(self.game_over_text, self.game_over_text_rect)
+
+
+class Clock(GameChild):
+
+    def __init__(self, parent):
+        GameChild.__init__(self, parent)
+        self.display_surface = self.get_display_surface()
+        self.time_filter = self.get_game().time_filter
+        self.messages = [ShadowedText(self, word, 12) for word in \
+                         ("three", "two", "one", "zero")]
+        self.rect = self.parent.parent.gate.frame_rect. \
+                    inflate(0, -self.messages[0].rect.h). \
+                    move(self.parent.parent.gate.frame_rect.w, 0)
+        self.deactivate()
+
+    def deactivate(self):
+        self.active = False
+
+    def activate(self):
+        self.active = True
+        self.elapsed = 0
+        self.limit = 30000 + self.parent.level_ii * 10000
+        self.ticking = False
+
+    def set_message_index(self, index):
+        self.message_ii = index
+
+    def finish(self):
+        self.set_message_index(4)
+        message = ShadowedText("%.2f" % self.elapsed)
+        message.play(message.blink)
+        if len(self.messages) < 5:
+            self.messages.append(message)
+        else:
+            self.messages[4] = message
+        self.ticking = False
+
+    def update(self):
+        if self.active:
+            if self.ticking:
+                self.elapsed += self.time_filter.get_last_frame_duration()
+                if self.elapsed >= self.limit:
+                    self.elapsed = self.limit
+                    self.set_message_index(3)
+                    self.parent.end()
+                    self.ticking = False
+            ratio = float(self.elapsed) / self.limit
+            mi = self.message_ii
+            if mi == 0:
+                color = (255, 31, 31)
+            elif mi == 1:
+                color = (255, 255, 31)
+            elif mi == 3:
+                color = (128, 128, 128)
+            else:
+                color = Color(0, 0, 0)
+                color.hsla = int(120 - ratio * 120), 100, 56, 100
+            self.messages[self.message_ii].update(color, self.rect.left + 4,
+                                                  int(round(self.rect.top + \
+                                                            self.rect.h * \
+                                                            ratio)))
+
+
+class ShadowedText(Animation):
+
+    def __init__(self, parent, text, size):
+        Animation.__init__(self, parent, self.blink, 250)
+        self.display_surface = self.get_display_surface()
+        self.visible = True
+        font = Font(self.get_resource("display", "font"), size)
+        font.set_bold(True)
+        self.surface = surface = font.render(text.upper(), True,
+                                             (255, 255, 255))
+        self.rect = surface.get_rect()
+
+    def blink(self):
+        self.visible = not self.visible
+
+    def update(self, color, x, y):
+        Animation.update(self)
+        if self.visible:
+            shadow_color = Color(*color)
+            h, s, l, a = shadow_color.hsla
+            shadow_color.hsla = h, abs(s - 24), abs(l - 40), 100
+            plate = Surface(self.rect.size, SRCALPHA)
+            plate.fill(shadow_color)
+            background = self.surface.copy()
+            background.blit(plate, (0, 0), None, BLEND_RGBA_MIN)
+            ds = self.display_surface
+            self.rect.midleft = x, y
+            ds.blit(background, self.rect)
+            plate.fill(color)
+            foreground = self.surface.copy()
+            foreground.blit(plate, (0, 0), None, BLEND_RGBA_MIN)
+            ds.blit(foreground, self.rect.move(1, 0))
 
 
 class Ship(Animation):
@@ -537,8 +675,8 @@ class Ship(Animation):
     def activate(self):
         self.active = True
         self.lines = [[self.max_length, -1,
-                       choice(((0, 255, 128), (255, 255, 0), (200, 90, 255)))] for \
-                      ii in xrange(12)]
+                       choice(((0, 255, 128), (255, 255, 0), (200, 90, 255)))] \
+                      for ii in xrange(12)]
         self.location = location = [-self.max_length / 2 - 1,
                                     self.display_surface.get_rect().centery, 0]
         node = choice(self.parent.nodes)
@@ -622,7 +760,7 @@ class Axes(GameChild):
         self.subscribe(self.respond)
 
     def respond(self, event):
-        if self.parent.active:
+        if self.parent.active and not self.suppressed:
             compare = self.delegate.compare
             names = ["up", "right", "down", "left"]
             for direction in names:
@@ -640,6 +778,14 @@ class Axes(GameChild):
                         elif direction not in self.waiting:
                             self.waiting.append(direction)
 
+    def suppress(self):
+        self.suppressed = True
+        for direction in self.directions.itervalues():
+            direction.on = False
+
+    def unsuppress(self):
+        self.suppressed = False
+
     def update(self):
         self.background.update()
         tx, ty, max_magnitude = 0, 0, 0
@@ -676,8 +822,8 @@ class Direction(GameChild):
         GameChild.__init__(self, parent)
         self.angle = angle
         self.on = False
-        self.attack = Transition(self, "roll-start")
-        self.release = Transition(self, "roll-end")
+        self.attack = Transition(self, "roll-start", 0)
+        self.release = Transition(self, "roll-end", -1)
 
     def get_magnitude(self):
         return self.attack.get() if self.on else self.release.get()
@@ -689,10 +835,10 @@ class Direction(GameChild):
 
 class Transition(GameChild):
 
-    def __init__(self, parent, name):
+    def __init__(self, parent, name, elapsed_index):
         GameChild.__init__(self, parent)
         self.nodeset = self.get_game().interpolator.get_nodeset(name)
-        self.elapsed = 0
+        self.elapsed = self.nodeset[elapsed_index].x
         self.time_filter = self.get_game().time_filter
 
     def get(self):