from engine.scene import Scene S=20 entities=[] class PacDot(Entity): s = Surface((S, S)) draw.circle(s, (255, 255, 0), (S//2, S//2), S//4) def __init__(self): super().__init__() CollideRect(self, Rect(0, 0, S, S), static=True, solid=False, cb=self.cb) Sprite(self, PacDot.s, 1) def cb(self): self.unregister() def path(start, tgt, x, y, trace, length): if start == tgt: return length if start is None or trace[y][x]: return False trace[y][x] = True u = path(start.up, tgt, x, y-1, trace, length + 1) d = path(start.down, tgt, x, y+1, trace, length + 1) l = path(start.left, tgt, x-1, y, trace, length + 1) r = path(start.right, tgt, x+1, y, trace, length + 1) best = None for subpath in (u, d, l, r): if subpath and (best is None or subpath < best): best = subpath return best class Node(): cpt = 0 def __init__(self): self.id = self.__class__.cpt self.__class__.cpt += 1 self.up = None self.down = None self.left = None self.right = None def children(self): children = [] for direction in ("up", "down", "left", "right"): node = getattr(self, direction) if node is not None: children.append((node, direction)) return children graph = None class Level(Entity): def __init__(self, path): global graph super().__init__() desc = image.load(res(path)) w, h = desc.get_size() GraphicsServer().resize((w * S, h * S)) graph = [[None for x in range(w)] for y in range(h)] self.surf = Surface((w * S, h * S)).convert() self.surf.fill((0, 0, 0)) wall = Surface((S, S)).convert() wall.fill((0, 0, 255)) for x, y in product(range(w), range(h)): col = desc.get_at((x, y)) if col == (0, 0, 255): CollideRect(self, Rect(x * S, y * S, S, S)) self.surf.blit(wall, (x * S, y * S)) elif col == (139, 139, 139): pc = PacDot() pc.x = x * S pc.y = y * S entities.append(pc) graph[y][x] = Node() elif col == (0, 0, 0) or col == (255, 0, 0): graph[y][x] = Node() for y, line in enumerate(graph): for x, node in enumerate(line): if node is None: continue node.left = graph[y][(x-1)%w] node.right = graph[y][(x+1)%w] node.up = graph[(y-1)%h][x] node.down = graph[(y+1)%h][x] Sprite(self, self.surf, 0) class MovingEntity(Entity): def __init__(self, surf): super().__init__() sprite = Sprite(self, surf, 2) self.phys = CollideRect( self, Rect(self.x, self.y, sprite.width, sprite.width), static=False) class Ghost(MovingEntity): def __init__(self): super().__init__(image.load(res('ghost.png')).convert()) self.script = Ghost.script def script(self): cur_node = graph[self.y//S][self.x//S] print(self.y//S, self.x//S) pacman = SceneManager().scene.entities['pacman'] # pacman_node = graph[pacman.y//S][pacman.x//S] x_dist = pacman.x - self.x y_dist = pacman.y - self.y s = 1 # self.phys.vx = s if x_dist > 0 else -s # self.phys.vy = s if y_dist > 0 else -s p = self.find_shortest_path(graph[pacman.y//S][pacman.x//S]) print([x[1] for x in p]) cur_dir = p[0][1] if cur_dir == "up": self.phys.vx = 0 self.phys.vy = -1 elif cur_dir == "down": self.phys.vx = 0 self.phys.vy = 1 elif cur_dir == "left": self.phys.vx = -1 self.phys.vy = 0 else: self.phys.vx = 1 self.phys.vy = 0 def find_shortest_path(self, final_node): cur_node = graph[self.y//S][self.x//S] # pacman_node = graph[pacman.y//S][pacman.x//S] children = cur_node.children() trace = [cur_node] + [x[0] for x in children] # if self.phys.vx < 0: cur_dir = "left" # elif self.phys.vx > 0: cur_dir = "right" # elif self.phys.vy < 0: cur_dir = "up" # else: cur_dir = "down" paths = [[x] for x in children] while 1: cur_len = len(paths) for path in paths[:cur_len]: for child in path[-1][0].children(): if child[0] is not None and child[0] not in trace: trace.append(child[0]) paths.append(path + [child]) if child[0] == final_node: return path paths = paths[cur_len:] class Lvl0(Scene): def load(self): self.add(Level('lvl0.png')) self.add(PacMan(S, S)) self.add(Ghost(S*6, S*2)) self.add(Ghost(S*6, S*13)) self.add(Ghost(S*18, S*13)) self.add(Ghost(S*8, S*23)) super().load() scene = Lvl0()