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)
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
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)
# 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
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
(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)
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
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):
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])
# 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 = []