diff --git a/actors/ghost.py b/actors/ghost.py index 8c71338..b37f599 100644 --- a/actors/ghost.py +++ b/actors/ghost.py @@ -3,18 +3,20 @@ import actors.ghost_behaviors as GB import pygame class Ghost(pygame.sprite.Sprite): - def __init__(self, name, color_enum, behavior_enum, position, speed): + def __init__(self, name, color_enum, behavior_enum, position, speed, start_location = (0, 0)): super().__init__() self.name = name self.color = color_enum.value self.behavior = behavior_enum - self.image = pygame.Surface((16, 16)) - self.image.fill(self.color) + self.image = pygame.Surface((24, 24)) self.rect = self.image.get_rect(center=position) self.speed = speed self.direction = pygame.Vector2(1, 0) self.mode = GhostMode.SCATTER self.home_position = position + self.location = start_location + self.frightned = pygame.Surface((24, 24)) + self.ghost_image = pygame.Surface((24, 24)) def decide_direction(self, ghost, pacman, maze): strategy = { @@ -27,12 +29,15 @@ class Ghost(pygame.sprite.Sprite): def update(self, maze, pacman): if self.mode == GhostMode.FRIGHTENED: + self.image = self.frightned self.change_direction_randomly(maze) else: + self.image = self.ghost_image self.direction = self.decide_direction(self, pacman, maze) new_pos = self.rect.move(self.direction.x * self.speed, self.direction.y * self.speed) - if not maze.is_wall(new_pos[0], new_pos[1]): + if not maze.is_wall(self.location[0], self.location[1]): self.rect = new_pos + self.location = (new_pos[0] % 32, new_pos[1] % 32) def change_direction_randomly(self, maze): import random @@ -41,29 +46,45 @@ class Ghost(pygame.sprite.Sprite): random.shuffle(directions) for d in directions: test_pos = self.rect.move(d.x * self.speed, d.y * self.speed) - if not maze.is_wall(test_pos.center): + if not maze.is_wall(test_pos.center[0], test_pos.center[1]): self.direction = d break def set_mode(self, mode: GhostMode): self.mode = mode if mode == GhostMode.FRIGHTENED: - self.image.fill((33, 33, 255)) # dark blue + self.image = self.frightned else: - self.image.fill(self.color) + self.image = self.ghost_image class Blinky(Ghost): - def __init__(self, position): - super().__init__("Blinky", GhostColor.BLINKY, GhostBehavior.BLINKY, position, speed=2) + def __init__(self, position, start_location): + super().__init__("Blinky", GhostColor.BLINKY, GhostBehavior.BLINKY, position, start_location=(0, 0), speed=2) + self.ghost_img = pygame.image.load("assets/blinky.png").convert_alpha() + self.ghost_image = pygame.transform.scale(self.ghost_img, (24, 24)) if self.ghost_img else None + self.fright_img = pygame.image.load("assets/frightned.png").convert_alpha() + self.frightened = pygame.transform.scale(self.fright_img, (24, 24)) if self.fright_img else None class Pinky(Ghost): - def __init__(self, position): - super().__init__("Pinky", GhostColor.PINKY, GhostBehavior.PINKY, position, speed=2) + def __init__(self, position, start_location): + super().__init__("Pinky", GhostColor.PINKY, GhostBehavior.PINKY, position, start_location=(0, 0), speed=2) + self.ghost_img = pygame.image.load("assets/pinky.png").convert_alpha() + self.ghost_image = pygame.transform.scale(self.ghost_img, (24, 24)) if self.ghost_img else None + self.fright_img = pygame.image.load("assets/frightned.png").convert_alpha() + self.frightened = pygame.transform.scale(self.fright_img, (24, 24)) if self.fright_img else None class Inky(Ghost): - def __init__(self, position): - super().__init__("Inky", GhostColor.INKY, GhostBehavior.INKY, position, speed=2) + def __init__(self, position, start_location): + super().__init__("Inky", GhostColor.INKY, GhostBehavior.INKY, position, start_location=(0, 0), speed=2) + self.ghost_img = pygame.image.load("assets/inky.png").convert_alpha() + self.ghost_image = pygame.transform.scale(self.ghost_img, (24, 24)) if self.ghost_img else None + self.fright_img = pygame.image.load("assets/frightned.png").convert_alpha() + self.frightened = pygame.transform.scale(self.fright_img, (24, 24)) if self.fright_img else None class Clyde(Ghost): - def __init__(self, position): - super().__init__("Clyde", GhostColor.CLYDE, GhostBehavior.CLYDE, position, speed=2) \ No newline at end of file + def __init__(self, position, start_location): + super().__init__("Clyde", GhostColor.CLYDE, GhostBehavior.CLYDE, position, start_location=(0, 0), speed=2) + self.ghost_img = pygame.image.load("assets/clyde.png").convert_alpha() + self.ghost_image = pygame.transform.scale(self.ghost_img, (24, 24)) if self.ghost_img else None + self.fright_img = pygame.image.load("assets/frightned.png").convert_alpha() + self.frightened = pygame.transform.scale(self.fright_img, (24, 24)) if self.fright_img else None \ No newline at end of file diff --git a/assets/blinky.png b/assets/blinky.png new file mode 100644 index 0000000..6c6c2c7 Binary files /dev/null and b/assets/blinky.png differ diff --git a/assets/clyde.png b/assets/clyde.png new file mode 100644 index 0000000..3935854 Binary files /dev/null and b/assets/clyde.png differ diff --git a/assets/frightned.png b/assets/frightned.png new file mode 100644 index 0000000..1a0ba57 Binary files /dev/null and b/assets/frightned.png differ diff --git a/assets/inky.png b/assets/inky.png new file mode 100644 index 0000000..15ecbc6 Binary files /dev/null and b/assets/inky.png differ diff --git a/assets/pinky.png b/assets/pinky.png new file mode 100644 index 0000000..d58ba11 Binary files /dev/null and b/assets/pinky.png differ diff --git a/maze.py b/maze.py index 2c3e911..709651d 100644 --- a/maze.py +++ b/maze.py @@ -34,7 +34,7 @@ class Maze: self.dots.add((x, y)) elif char == "*": self.power_pellets.add((x, y)) - elif char == "P": + elif char == "M": self.pacman_start = (x * TILE_SIZE + TILE_SIZE // 2, y * TILE_SIZE + TILE_SIZE // 2 + 32) self.pacman_location = (x, y) @@ -62,6 +62,9 @@ class Maze: def is_wall(self, x, y): return self.tile_at(x, y) == "W" + def is_ghost_home(self, x, y): + return self.tile_at(x, y) == "H" + def collect_dot(self, x, y): """Mark a dot as collected. Return True if there was a dot or power pellet.""" pos = (x, y) diff --git a/maze/pacman_maze.txt b/maze/pacman_maze.txt index 729633f..8b6a26d 100644 --- a/maze/pacman_maze.txt +++ b/maze/pacman_maze.txt @@ -10,12 +10,12 @@ W.......W.....W.....W.......W WWWWWWW.WWWWW.W.WWWWW.WWWWWWW W W.WWWWW.W.WWWWW.W W W W...............W W -WWWWWWW.W.WWW---WWW.W.WWWWWWW -........W.W W.W........ -WWWWWWW.W.W W.W.WWWWWWW -W W.W.W W.W.W W +WWWWWWW.W.WWWHHHWWW.W.WWWWWWW +........W.WHBHHHPHW.W........ +WWWWWWW.W.WHHHHHHHW.W.WWWWWWW +W W.W.WHIHHHCHW.W.W W W W.W.WWWWWWWWW.W.W W -WWWWWWW.......P.......WWWWWWW +WWWWWWW.......M.......WWWWWWW W.......WWWWWWWWWWWWW.......W W.WWWWW.W W...W W.WWWWW.W W*WWWWW.WWWWW.W.WWWWW.WWWWW*W diff --git a/pman.py b/pman.py index e920388..a641839 100644 --- a/pman.py +++ b/pman.py @@ -7,7 +7,7 @@ from actors.ghost_mode_controller import GhostModeController from hud import HUD from maze import Maze -__version__ = "0.4.1" +__version__ = "0.4.2" # Constants HAT_REPEAT_DELAY = 300 # milliseconds before first repeat @@ -62,10 +62,10 @@ class Game: """ offset = 20 # spread out a little bit inside ghost home - self.blinky = Blinky((center_position[0] - offset, center_position[1] - offset)) - self.pinky = Pinky((center_position[0] + offset, center_position[1] - offset)) - self.inky = Inky((center_position[0] - offset, center_position[1] + offset)) - self.clyde = Clyde((center_position[0] + offset, center_position[1] + offset)) + self.blinky = Blinky((center_position[0] - 64, center_position[1] - 32), start_location=(13, 14)) + self.pinky = Pinky((center_position[0] + 64, center_position[1] - 32), start_location=(17, 14)) + self.inky = Inky((center_position[0] - 64, center_position[1] + 32), start_location=(13, 16)) + self.clyde = Clyde((center_position[0] + 64, center_position[1] + 32), start_location=(17, 16)) return pygame.sprite.Group(self.blinky, self.pinky, self.inky, self.clyde) @@ -120,21 +120,29 @@ class Game: case pygame.K_RIGHT: if self.maze.is_wall(self.player.location[0] + 1, self.player.location[1]): break + elif self.maze.is_ghost_home(self.player.location[0] + 1, self.player.location[1]): + break self.player.direction = PlayerDirection.DirectionRight self.player.move_right() case pygame.K_LEFT: if self.maze.is_wall(self.player.location[0] - 1, self.player.location[1]): break + elif self.maze.is_ghost_home(self.player.location[0] - 1, self.player.location[1]): + break self.player.direction = PlayerDirection.DirectionLeft self.player.move_left() case pygame.K_UP: if self.maze.is_wall(self.player.location[0], self.player.location[1] - 1): break + elif self.maze.is_ghost_home(self.player.location[0], self.player.location[1] - 1): + break self.player.direction = PlayerDirection.DirectionUp self.player.move_up() case pygame.K_DOWN: if self.maze.is_wall(self.player.location[0], self.player.location[1] + 1): break + elif self.maze.is_ghost_home(self.player.location[0], self.player.location[1] + 1): + break self.player.direction = PlayerDirection.DirectionDown self.player.move_down() case pygame.JOYHATMOTION: @@ -147,24 +155,32 @@ class Game: if event.type == pygame.USEREVENT and event.dict.get("type_name") == "JOYHATREPEAT": if self.maze.is_wall(self.player.location[0] + 1, self.player.location[1]): break + elif self.maze.is_ghost_home(self.player.location[0] + 1, self.player.location[1]): + break self.player.direction = PlayerDirection.DirectionRight self.player.move_right() elif self.hat_x == -1: if event.type == pygame.USEREVENT and event.dict.get("type_name") == "JOYHATREPEAT": if self.maze.is_wall(self.player.location[0] - 1, self.player.location[1]): break + elif self.maze.is_ghost_home(self.player.location[0] - 1, self.player.location[1]): + break self.player.direction = PlayerDirection.DirectionLeft self.player.move_left() elif self.hat_y == 1: if event.type == pygame.USEREVENT and event.dict.get("type_name") == "JOYHATREPEAT": if self.maze.is_wall(self.player.location[0], self.player.location[1] - 1): break + elif self.maze.is_ghost_home(self.player.location[0], self.player.location[1] - 1): + break self.player.direction = PlayerDirection.DirectionUp self.player.move_up() elif self.hat_y == -1: if event.type == pygame.USEREVENT and event.dict.get("type_name") == "JOYHATREPEAT": if self.maze.is_wall(self.player.location[0], self.player.location[1] + 1): break + elif self.maze.is_ghost_home(self.player.location[0], self.player.location[1] + 1): + break self.player.direction = PlayerDirection.DirectionDown self.player.move_down() @@ -184,6 +200,7 @@ class Game: self.hud.add_points(10) case "power": self.hud.add_points(50) + self.ghost_mode_controller.trigger_frightened() if __name__ == "__main__": pman = Game()