class Boxes: def __init__(self): self.screen = Screen(Vector(600, 400), 'data/background.png') self.frame = Frame(self.screen, Rect(64, 64, 320, 320)) tile_factory = TileFactory('data/tiles.conf') self.tm = TiledMap(self.frame, tile_factory) self.player = Sprite(self.frame, tile_factory.get('b.tail'), Vector(4, 1), speed=2) self.tm.set_map(BOXMAP) self.draw() self.events = None def draw(self): self.tm.draw() self.player.draw() pygame.display.update() def move(self, direction): nearpos = self.player.pos + direction farpos = nearpos + direction near = self.tm.at(nearpos) far = self.tm.at(farpos) if near == '#': return if near in 'xX' and far in '#xX': return else: # move possible moves = MoveGroup() self.player.add_move(direction) moves.add(self.player) if near in 'xX': # crate moved floor = near=='x' and '.' or '*' insert = far=='*' and 'X' or 'x' moves.add(MapMove(self.tm, nearpos, direction, 1, floor_tile=floor, insert_tile=insert)) wait_for_move(moves, self.screen, self.draw, 0.01) self.tm.cache_map() self.draw() self.check_complete() def check_complete(self): s = self.tm.get_map() if s.count('X') == 4: print("\nCongratulations!\n") time.sleep(2) self.events.exit_signalled() def run(self): self.events = EventGenerator() self.events.add_listener(FigureMoveListener(self.move)) self.events.add_listener(ExitListener(self.events.exit_signalled)) with draw_timer(self, self.events): self.events.event_loop()
class CollectFruit: def __init__(self, screen): self.screen = screen self.frame = Frame(self.screen, Rect(64, 64, 320, 320)) tile_factory = TileFactory('data/tiles.conf') self.tm = TiledMap(self.frame, tile_factory) self.player = Sprite(self.frame, tile_factory.get('b.pac_right'), Vector(4, 1), speed=2) self.tm.set_map(FRUITMAP) self.draw() self.events = None self.score = 0 def draw(self): self.tm.draw() self.player.draw() pygame.display.update() def move(self, direction): nearpos = self.player.pos + direction near = self.tm.at(nearpos) if near == '#': return self.player.add_move(direction) wait_for_move(self.player, self.screen, self.draw, 0.01) self.check_player_square() def check_player_square(self): field = self.tm.at(self.player.pos) if field == '*': time.sleep(1) self.events.exit_signalled() elif field in 'abcdefgh': self.score += 100 self.tm.set_tile(self.player.pos, '.') self.tm.cache_map() self.draw() def run(self): self.events = EventGenerator() self.events.add_listener(FigureMoveListener(self.move)) self.events.add_listener(ExitListener(self.events.exit_signalled)) with draw_timer(self, self.events): self.events.event_loop()
class FrutrisLevel: def __init__(self, frame, tile_factory, level): self.tmap = TiledMap(frame, tile_factory) self.tmap.set_map(level) def insert(self, pos, fruit): self.tmap.set_tile(pos, fruit) self.tmap.cache_map() def is_pos_in_box(self, pos): if (0 <= pos.x < self.tmap.size.x) and (0 <= pos.y < self.tmap.size.y): return True def are_positions_empty(self, positions): for pos in positions: if self.tmap.at(pos) != '.': return False return True def trace_multiplets(self, pos, trace, char, taboo): """Recursively looks for quartets of identical bricks.""" if not self.is_pos_in_box(pos) \ or pos in taboo \ or self.tmap.at(pos) != char or pos in trace: return trace.add(pos) self.trace_multiplets(pos + LEFT, trace, char, taboo) self.trace_multiplets(pos + RIGHT, trace, char, taboo) self.trace_multiplets(pos + DOWN, trace, char, taboo) def find_multiplets(self): """Returns a list of multiplet positions""" multiplets = FruitMultiplets() taboo = [] for x in range(1, self.tmap.size.x - 1): for y in range(self.tmap.size.y): pos = Vector(x, y) if self.tmap.at(pos) in ('.', '#'): continue found = set() char = self.tmap.at(pos) self.trace_multiplets(pos, found, char, taboo) if len(found) >= 4: multiplets.add_multiplet(found) taboo.extend(found) return multiplets def get_dropped_bricks(self): drop_moves = MoveGroup() for x in range(self.tmap.size.x): pos = Vector(x, self.tmap.size.y - 1) while pos.y > 0: pos_above = pos + UP if self.tmap.at(pos) == '.' and self.tmap.at(pos_above) != '.': drop_moves.add(MapMove(self.tmap, pos_above, DOWN, speed=4)) pos = pos_above return drop_moves def get_explosions(self, multiplets): explosions = MoveGroup() for pos in multiplets.get_positions(): self.tmap.set_tile(pos, '.') explosions.add(AnimatedTile(EXPLOSION, self.tmap.tile_factory, self.tmap.frame, pos)) self.tmap.cache_map() if len(explosions.moves) == 0: return None return explosions def box_overflow(self): if self.get_stack_size() == self.tmap.size.y - 1: return True def get_stack_size(self): """Returns height of the fruit stack.""" y = 0 while y < self.tmap.size.y: for x in range(1, self.tmap.size.x - 1): char = self.tmap.at(Vector(x, y)) if char != '.': return self.tmap.size.y - y - 1 y += 1 return 0 def draw(self): self.tmap.draw()