Added ghost image files. /JL

This commit is contained in:
2025-04-20 21:30:23 +02:00
parent 97c06fd3cf
commit c95c755e3f
9 changed files with 67 additions and 26 deletions

View File

@@ -3,18 +3,20 @@ import actors.ghost_behaviors as GB
import pygame import pygame
class Ghost(pygame.sprite.Sprite): 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__() super().__init__()
self.name = name self.name = name
self.color = color_enum.value self.color = color_enum.value
self.behavior = behavior_enum self.behavior = behavior_enum
self.image = pygame.Surface((16, 16)) self.image = pygame.Surface((24, 24))
self.image.fill(self.color)
self.rect = self.image.get_rect(center=position) self.rect = self.image.get_rect(center=position)
self.speed = speed self.speed = speed
self.direction = pygame.Vector2(1, 0) self.direction = pygame.Vector2(1, 0)
self.mode = GhostMode.SCATTER self.mode = GhostMode.SCATTER
self.home_position = position 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): def decide_direction(self, ghost, pacman, maze):
strategy = { strategy = {
@@ -27,12 +29,15 @@ class Ghost(pygame.sprite.Sprite):
def update(self, maze, pacman): def update(self, maze, pacman):
if self.mode == GhostMode.FRIGHTENED: if self.mode == GhostMode.FRIGHTENED:
self.image = self.frightned
self.change_direction_randomly(maze) self.change_direction_randomly(maze)
else: else:
self.image = self.ghost_image
self.direction = self.decide_direction(self, pacman, maze) self.direction = self.decide_direction(self, pacman, maze)
new_pos = self.rect.move(self.direction.x * self.speed, self.direction.y * self.speed) 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.rect = new_pos
self.location = (new_pos[0] % 32, new_pos[1] % 32)
def change_direction_randomly(self, maze): def change_direction_randomly(self, maze):
import random import random
@@ -41,29 +46,45 @@ class Ghost(pygame.sprite.Sprite):
random.shuffle(directions) random.shuffle(directions)
for d in directions: for d in directions:
test_pos = self.rect.move(d.x * self.speed, d.y * self.speed) 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 self.direction = d
break break
def set_mode(self, mode: GhostMode): def set_mode(self, mode: GhostMode):
self.mode = mode self.mode = mode
if mode == GhostMode.FRIGHTENED: if mode == GhostMode.FRIGHTENED:
self.image.fill((33, 33, 255)) # dark blue self.image = self.frightned
else: else:
self.image.fill(self.color) self.image = self.ghost_image
class Blinky(Ghost): class Blinky(Ghost):
def __init__(self, position): def __init__(self, position, start_location):
super().__init__("Blinky", GhostColor.BLINKY, GhostBehavior.BLINKY, position, speed=2) 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): class Pinky(Ghost):
def __init__(self, position): def __init__(self, position, start_location):
super().__init__("Pinky", GhostColor.PINKY, GhostBehavior.PINKY, position, speed=2) 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): class Inky(Ghost):
def __init__(self, position): def __init__(self, position, start_location):
super().__init__("Inky", GhostColor.INKY, GhostBehavior.INKY, position, speed=2) 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): class Clyde(Ghost):
def __init__(self, position): def __init__(self, position, start_location):
super().__init__("Clyde", GhostColor.CLYDE, GhostBehavior.CLYDE, position, speed=2) 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

BIN
assets/blinky.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
assets/clyde.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
assets/frightned.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
assets/inky.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
assets/pinky.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -34,7 +34,7 @@ class Maze:
self.dots.add((x, y)) self.dots.add((x, y))
elif char == "*": elif char == "*":
self.power_pellets.add((x, y)) 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_start = (x * TILE_SIZE + TILE_SIZE // 2, y * TILE_SIZE + TILE_SIZE // 2 + 32)
self.pacman_location = (x, y) self.pacman_location = (x, y)
@@ -62,6 +62,9 @@ class Maze:
def is_wall(self, x, y): def is_wall(self, x, y):
return self.tile_at(x, y) == "W" 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): def collect_dot(self, x, y):
"""Mark a dot as collected. Return True if there was a dot or power pellet.""" """Mark a dot as collected. Return True if there was a dot or power pellet."""
pos = (x, y) pos = (x, y)

View File

@@ -10,12 +10,12 @@ W.......W.....W.....W.......W
WWWWWWW.WWWWW.W.WWWWW.WWWWWWW WWWWWWW.WWWWW.W.WWWWW.WWWWWWW
W W.WWWWW.W.WWWWW.W W W W.WWWWW.W.WWWWW.W W
W W...............W W W W...............W W
WWWWWWW.W.WWW---WWW.W.WWWWWWW WWWWWWW.W.WWWHHHWWW.W.WWWWWWW
........W.W W.W........ ........W.WHBHHHPHW.W........
WWWWWWW.W.W W.W.WWWWWWW WWWWWWW.W.WHHHHHHHW.W.WWWWWWW
W W.W.W W.W.W W W W.W.WHIHHHCHW.W.W W
W W.W.WWWWWWWWW.W.W W W W.W.WWWWWWWWW.W.W W
WWWWWWW.......P.......WWWWWWW WWWWWWW.......M.......WWWWWWW
W.......WWWWWWWWWWWWW.......W W.......WWWWWWWWWWWWW.......W
W.WWWWW.W W...W W.WWWWW.W W.WWWWW.W W...W W.WWWWW.W
W*WWWWW.WWWWW.W.WWWWW.WWWWW*W W*WWWWW.WWWWW.W.WWWWW.WWWWW*W

27
pman.py
View File

@@ -7,7 +7,7 @@ from actors.ghost_mode_controller import GhostModeController
from hud import HUD from hud import HUD
from maze import Maze from maze import Maze
__version__ = "0.4.1" __version__ = "0.4.2"
# Constants # Constants
HAT_REPEAT_DELAY = 300 # milliseconds before first repeat HAT_REPEAT_DELAY = 300 # milliseconds before first repeat
@@ -62,10 +62,10 @@ class Game:
""" """
offset = 20 # spread out a little bit inside ghost home offset = 20 # spread out a little bit inside ghost home
self.blinky = Blinky((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] + offset, center_position[1] - offset)) self.pinky = Pinky((center_position[0] + 64, center_position[1] - 32), start_location=(17, 14))
self.inky = Inky((center_position[0] - offset, center_position[1] + offset)) self.inky = Inky((center_position[0] - 64, center_position[1] + 32), start_location=(13, 16))
self.clyde = Clyde((center_position[0] + offset, center_position[1] + offset)) 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) return pygame.sprite.Group(self.blinky, self.pinky, self.inky, self.clyde)
@@ -120,21 +120,29 @@ class Game:
case pygame.K_RIGHT: case pygame.K_RIGHT:
if self.maze.is_wall(self.player.location[0] + 1, self.player.location[1]): if self.maze.is_wall(self.player.location[0] + 1, self.player.location[1]):
break break
elif self.maze.is_ghost_home(self.player.location[0] + 1, self.player.location[1]):
break
self.player.direction = PlayerDirection.DirectionRight self.player.direction = PlayerDirection.DirectionRight
self.player.move_right() self.player.move_right()
case pygame.K_LEFT: case pygame.K_LEFT:
if self.maze.is_wall(self.player.location[0] - 1, self.player.location[1]): if self.maze.is_wall(self.player.location[0] - 1, self.player.location[1]):
break break
elif self.maze.is_ghost_home(self.player.location[0] - 1, self.player.location[1]):
break
self.player.direction = PlayerDirection.DirectionLeft self.player.direction = PlayerDirection.DirectionLeft
self.player.move_left() self.player.move_left()
case pygame.K_UP: case pygame.K_UP:
if self.maze.is_wall(self.player.location[0], self.player.location[1] - 1): if self.maze.is_wall(self.player.location[0], self.player.location[1] - 1):
break break
elif self.maze.is_ghost_home(self.player.location[0], self.player.location[1] - 1):
break
self.player.direction = PlayerDirection.DirectionUp self.player.direction = PlayerDirection.DirectionUp
self.player.move_up() self.player.move_up()
case pygame.K_DOWN: case pygame.K_DOWN:
if self.maze.is_wall(self.player.location[0], self.player.location[1] + 1): if self.maze.is_wall(self.player.location[0], self.player.location[1] + 1):
break break
elif self.maze.is_ghost_home(self.player.location[0], self.player.location[1] + 1):
break
self.player.direction = PlayerDirection.DirectionDown self.player.direction = PlayerDirection.DirectionDown
self.player.move_down() self.player.move_down()
case pygame.JOYHATMOTION: case pygame.JOYHATMOTION:
@@ -147,24 +155,32 @@ class Game:
if event.type == pygame.USEREVENT and event.dict.get("type_name") == "JOYHATREPEAT": 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]): if self.maze.is_wall(self.player.location[0] + 1, self.player.location[1]):
break break
elif self.maze.is_ghost_home(self.player.location[0] + 1, self.player.location[1]):
break
self.player.direction = PlayerDirection.DirectionRight self.player.direction = PlayerDirection.DirectionRight
self.player.move_right() self.player.move_right()
elif self.hat_x == -1: elif self.hat_x == -1:
if event.type == pygame.USEREVENT and event.dict.get("type_name") == "JOYHATREPEAT": 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]): if self.maze.is_wall(self.player.location[0] - 1, self.player.location[1]):
break break
elif self.maze.is_ghost_home(self.player.location[0] - 1, self.player.location[1]):
break
self.player.direction = PlayerDirection.DirectionLeft self.player.direction = PlayerDirection.DirectionLeft
self.player.move_left() self.player.move_left()
elif self.hat_y == 1: elif self.hat_y == 1:
if event.type == pygame.USEREVENT and event.dict.get("type_name") == "JOYHATREPEAT": 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): if self.maze.is_wall(self.player.location[0], self.player.location[1] - 1):
break break
elif self.maze.is_ghost_home(self.player.location[0], self.player.location[1] - 1):
break
self.player.direction = PlayerDirection.DirectionUp self.player.direction = PlayerDirection.DirectionUp
self.player.move_up() self.player.move_up()
elif self.hat_y == -1: elif self.hat_y == -1:
if event.type == pygame.USEREVENT and event.dict.get("type_name") == "JOYHATREPEAT": 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): if self.maze.is_wall(self.player.location[0], self.player.location[1] + 1):
break break
elif self.maze.is_ghost_home(self.player.location[0], self.player.location[1] + 1):
break
self.player.direction = PlayerDirection.DirectionDown self.player.direction = PlayerDirection.DirectionDown
self.player.move_down() self.player.move_down()
@@ -184,6 +200,7 @@ class Game:
self.hud.add_points(10) self.hud.add_points(10)
case "power": case "power":
self.hud.add_points(50) self.hud.add_points(50)
self.ghost_mode_controller.trigger_frightened()
if __name__ == "__main__": if __name__ == "__main__":
pman = Game() pman = Game()