Make buttons trigger
authorNeil <neil@dip.sun.ac.za>
Thu, 18 Apr 2013 14:27:52 +0000 (16:27 +0200)
committerNeil <neil@dip.sun.ac.za>
Thu, 18 Apr 2013 14:27:52 +0000 (16:27 +0200)
erdslangetjie/__main__.py
erdslangetjie/level.py
erdslangetjie/player.py

index 74a0c33a2509ac939988175ea4de3624d6a033f2..ad07468b327a48859cb6bd7ad109985cccfd7e84 100644 (file)
@@ -67,18 +67,22 @@ class GameWindow(RelativeLayout):
         for tile_line in tiles:
             bx = 0
             for tile in tile_line:
-                node = Widget(size=(TILE_SIZE, TILE_SIZE),
-                        pos=(bx, by),
-                        size_hint=(None, None))
-                self.add_widget(node)
-                with node.canvas:
-                    Color(1, 1, 1)
-                    Rectangle(pos=node.pos, size=node.size,
-                            texture=tile.texture)
-                self.tiles[(bx, by)] = node
+                self.draw_tile((bx, by), tile)
                 bx += TILE_SIZE
             by += TILE_SIZE
 
+    def draw_tile(self, pos, tile):
+        if pos in self.tiles:
+            self.remove_widget(self.tiles[pos])
+        node = Widget(size=(TILE_SIZE, TILE_SIZE),
+                pos=pos, size_hint=(None, None))
+        self.add_widget(node)
+        with node.canvas:
+            Color(1, 1, 1)
+            Rectangle(pos=node.pos, size=node.size,
+                    texture=tile.texture)
+        self.tiles[pos] = node
+
     def draw_player(self):
         if self.player_tile:
             self.remove_widget(self.player_tile)
@@ -180,18 +184,20 @@ class GameWindow(RelativeLayout):
         if not self.level_obj:
             return
         self.player.move(direction, self.level_obj)
-        self.draw_player()
         self.check_state()
-        if not self.timer_set:
-            self.reset_timer()
+        self.do_nemesis_move()
+
+    def do_nemesis_move(self):
+        self.nemesis.move(self.level_obj)
+        self.check_state()
+        self.reset_timer()
+        self.draw_nemesis()
+        self.draw_player()
 
     def timed_move(self, event):
         if not self.level_obj:
             return
-        self.nemesis.move(self.level_obj, self.check_caught)
-        self.draw_nemesis()
-        self.check_state()
-        self.reset_timer()
+        self.do_nemesis_move()
 
     def reset_timer(self):
         self.timer_set = True
@@ -220,14 +226,25 @@ class GameWindow(RelativeLayout):
         return False
 
     def check_state(self):
+        if not self.level_obj:
+            return
         if self.level_obj.at_exit(self.player.pos):
             # Jump to next level
             self.level_obj = self.level_list.advance_to_next_level()
             if not self.reset_level():
                 self.app.game_over(True)
+            return
         elif self.check_caught():
             # Caught
             self.app.game_over(False)
+            return
+        elif self.level_obj.is_button(self.player.pos):
+            self.level_obj.trigger_button(self.player.pos)
+        elif self.level_obj.is_button(self.nemesis.pos):
+            self.level_obj.trigger_button(self.nemesis.pos)
+        for map_pos, new_tile in self.level_obj.get_changed_tiles():
+            pos = (map_pos[0] * TILE_SIZE, map_pos[1] * TILE_SIZE)
+            self.draw_tile(pos, new_tile)
 
     def _calc_mouse_pos(self, pos):
         pos = self.to_local(*pos)
index c722b563873c76034e73548e2a723c1ba0cfdf14..fc23cc626238bb965d69eea370098cffad96293f 100644 (file)
@@ -75,8 +75,13 @@ class Level(object):
                     # gate up
                     image = load_image('tiles/gate_up.png')
         elif c == BUTTON:
-            image = load_image('tiles/button.png')
-            self._buttons[pos] = 'active'
+            if not pos in self._buttons:
+                image = load_image('tiles/button.png')
+                self._buttons[pos] = 'active'
+            elif self._buttons[pos] == 'active':
+                image = load_image('tiles/button.png')
+            else:
+                image = load_image('tiles/floor.png')
         if image is None:
             raise RuntimeError('Unknown tile type %s at %s' % (c, pos))
         return image
@@ -84,17 +89,25 @@ class Level(object):
     def validate(self):
         entry_points = 0
         exit_points = 0
+        gates = 0
+        buttons = 0
         for line in self._data:
             if ENTRY in line:
                 entry_points += line.count(ENTRY)
             if EXIT in line:
                 exit_points += line.count(EXIT)
+            if BUTTON in line:
+                buttons += line.count(BUTTON)
+            if GATE in line:
+                gates += line.count(GATE)
         if entry_points == 0:
             raise RuntimeError('No entry point')
         if entry_points > 1:
             raise RuntimeError('Multiple entry points')
         if exit_points == 0:
             raise RuntimeError('No exit')
+        if gates != buttons:
+            raise RuntimeError('The number of buttons and gates differ')
 
     def get_tiles(self):
         return self._tiles
@@ -122,10 +135,14 @@ class Level(object):
                 (pos[0] - 1, pos[1] + 1), (pos[0] + 1, pos[1] - 1)]:
             if not self._in_limits(new_pos):
                 continue
-            tile = self._data[new_pos[1]][new_pos[0]]
-            new_tile = self._get_tile_image(new_pos, tile)
-            self._tiles[new_pos[1]][new_pos[0]] = new_tile
-            self._changed.append((new_pos, new_tile))
+            # Update display to changed status
+            self._fix_tile(new_pos)
+
+    def _fix_tile(self, pos):
+        tile = self._data[pos[1]][pos[0]]
+        new_tile = self._get_tile_image(pos, tile)
+        self._tiles[pos[1]][pos[0]] = new_tile
+        self._changed.append((pos, new_tile))
 
     def get_size(self):
         return len(self._tiles[0]), len(self._tiles)
@@ -211,10 +228,14 @@ class Level(object):
         if tile == WALL or tile == ENTRY:
             return True
         if tile == GATE:
+            print tile, pos, self._gates[pos]
             if self._gates[pos] != -1:
                 return True
         return False
 
+    def calc_dist(self, pos1, pos2):
+        return abs(pos1[0] - pos2[0]) + abs(pos1[1] - pos2[1])
+
     def is_gate(self, pos):
         return self._data[pos[1]][pos[0]] == GATE
 
@@ -227,10 +248,18 @@ class Level(object):
         if not self._buttons[pos] == 'active':
             return False
         # Find the closest gate down gate and trigger it
-        gate_pos = pos
-
-        self._changed.append((pos, self.get_single_tile(pos)))
-        self._changed.append((gate_pos, self.get_single_tile(pos)))
+        mindist = 99999
+        gate_pos = None
+        for cand in self._gates:
+            dist = self.calc_dist(pos, cand)
+            if dist < mindist:
+                gate_pos = cand
+                mindist = dist
+        if gate_pos:
+            self._buttons[pos] == 'pressed'
+            self._gates[gate_pos] = 3  # Raise gate
+            self._fix_tile(pos)
+            self._fix_tile(gate_pos)
 
     def damage_gate(self, pos):
         if not self.is_gate(pos):
index fd445549ed530acbf1f71cb5d8e20af3dbedda08..e0ac771d3af9e046f265cab3efc03525015ab2cb 100644 (file)
@@ -45,7 +45,7 @@ class Nemesis(FigureSprite):
         self.reset_pos()
         self.been = []
 
-    def move(self, level, caught):
+    def move(self, level):
         if not self.on_board():
             # Advance towards the map a step at a time
             self.pos = (self.pos[0] + 1, self.pos[1])
@@ -55,15 +55,12 @@ class Nemesis(FigureSprite):
         # AI goes here
         steps = 0
         self.been.append(self.pos)
-        for direction in [(1, 0), (-1, 0), (0, -1), (0, 1)] * 2:
+        for direction in [(1, 0), (-1, 0), (0, -1), (0, 1)]:
             new_pos = (self.pos[0] + direction[0], self.pos[1] + direction[1])
             if self.can_move(direction, level) and new_pos not in self.been:
                 self.pos = new_pos
                 self.been.append(new_pos)
                 steps += 1
-            if steps >= 2:
-                break
-            if caught():
                 break
         if steps == 0:
             self.been = []