diff --git a/pman.py b/pman.py index 3c53f08..6d489af 100644 --- a/pman.py +++ b/pman.py @@ -7,174 +7,183 @@ from actors.ghost_mode_controller import GhostModeController from hud import HUD from maze import Maze -__version__ = "0.3.4" +__version__ = "0.4.0" # Constants HAT_REPEAT_DELAY = 300 # milliseconds before first repeat HAT_REPEAT_INTERVAL = 100 # milliseconds between repeats -# State -hat_direction = (0, 0) -hat_timer = 0 -hat_first_press = True - -def spawn_ghosts(center_position): - """ - Spawns up to 4 ghosts at the center of the maze ("ghost house"). - - Args: - center_position (tuple): (x, y) coordinates for spawn point. - - Returns: - pygame.sprite.Group: A group containing all ghost instances. - """ - offset = 20 # spread out a little bit inside ghost home - - blinky = Blinky((center_position[0] - offset, center_position[1] - offset)) - pinky = Pinky((center_position[0] + offset, center_position[1] - offset)) - inky = Inky((center_position[0] - offset, center_position[1] + offset)) - clyde = Clyde((center_position[0] + offset, center_position[1] + offset)) - - return pygame.sprite.Group(blinky, pinky, inky, clyde) - -def handle_hat_repeat(): - global hat_timer, hat_first_press - now = pygame.time.get_ticks() - if hat_direction != (0, 0): - if hat_first_press: - if now - hat_timer >= HAT_REPEAT_DELAY: - hat_timer = now - hat_first_press = False - post_hat_repeat_event() - else: - if now - hat_timer >= HAT_REPEAT_INTERVAL: - hat_timer = now - post_hat_repeat_event() - -def post_hat_repeat_event(): - pygame.event.post(pygame.event.Event(pygame.USEREVENT, { - "type_name": "JOYHATREPEAT", - "value": hat_direction - })) - -def main() -> None: - global hat_direction, hat_timer, hat_first_press - - pygame.init() - pygame.key.set_repeat(200) - joystick_count = pygame.joystick.get_count() +class Game: + def __init__(self): + #states + self.hat_direction = (0, 0) + self.hat_timer = 0 + self.hat_first_press = True + self.setup() + self.running = True + while self.running: + self.main_loop() - joysticks = {} - - screen_width, screen_height = (32*29), (32*30)+32 - screen = pygame.display.set_mode((screen_width, screen_height)) - pygame.display.set_caption("Pac-Man " + __version__) + if self.joysticks: + self.joysticks[self.joy.get_instance_id()].controllers[0].close() + + pygame.quit() + + def setup(self): + pygame.init() + pygame.key.set_repeat(200) + self.joystick_count = pygame.joystick.get_count() + + self.joysticks = {} + + self.screen_width, self.screen_height = (32*29), (32*30)+32 + self.screen = pygame.display.set_mode((self.screen_width, self.screen_height)) + pygame.display.set_caption("Pac-Man " + __version__) - cherry_img = pygame.image.load("assets/cherry.png").convert_alpha() - hud = HUD(screen_width, screen_height, cherry_image=cherry_img) - maze = Maze("maze/pacman_maze.txt") + self.cherry_img = pygame.image.load("assets/cherry.png").convert_alpha() + self.hud = HUD(self.screen_width, self.screen_height, cherry_image=self.cherry_img) + self.maze = Maze("maze/pacman_maze.txt") - player = ActorPacman(screen, center=maze.pacman_start, start_location=maze.pacman_location, maze=maze) - ghost_mode_controller = GhostModeController() - ghost_home_center = (screen_width // 2, (screen_height) // 2) - ghosts = spawn_ghosts(ghost_home_center) - clock = pygame.time.Clock() + self.player = ActorPacman(self.screen, center=self.maze.pacman_start, start_location=self.maze.pacman_location, maze=self.maze) + self.ghost_mode_controller = GhostModeController() + self.ghost_home_center = (self.screen_width // 2, (self.screen_height) // 2) + self.ghosts = self.spawn_ghosts(self.ghost_home_center) + self.clock = pygame.time.Clock() + + def spawn_ghosts(self, center_position): + """ + Spawns up to 4 ghosts at the center of the maze ("ghost house"). + + Args: + center_position (tuple): (x, y) coordinates for spawn point. + + Returns: + pygame.sprite.Group: A group containing all ghost instances. + """ + offset = 20 # spread out a little bit inside ghost home + + blinky = Blinky((center_position[0] - offset, center_position[1] - offset)) + pinky = Pinky((center_position[0] + offset, center_position[1] - offset)) + inky = Inky((center_position[0] - offset, center_position[1] + offset)) + clyde = Clyde((center_position[0] + offset, center_position[1] + offset)) + + return pygame.sprite.Group(blinky, pinky, inky, clyde) - running = True - while running: - screen.fill(Colors.Black.value) - pygame.event.pump() + def handle_hat_repeat(self): + now = pygame.time.get_ticks() + if self.hat_direction != (0, 0): + if self.hat_first_press: + if now - self.hat_timer >= HAT_REPEAT_DELAY: + self.hat_timer = now + self.hat_first_press = False + self.post_hat_repeat_event() + else: + if now - self.hat_timer >= HAT_REPEAT_INTERVAL: + self.hat_timer = now + self.post_hat_repeat_event() + + def post_hat_repeat_event(self): + pygame.event.post(pygame.event.Event(pygame.USEREVENT, { + "type_name": "JOYHATREPEAT", + "value": self.hat_direction + })) + + def main_loop(self): + self.screen.fill(Colors.Black.value) + + self.handle_events() + + # In your main game loop: + self.handle_hat_repeat() + self.hud.draw(self.screen) + self.maze.draw(self.screen) + self.player.update() + self.player.draw() + self.ghost_mode_controller.update() + self.current_mode = self.ghost_mode_controller.mode + + for ghost in self.ghosts: + ghost.set_mode(self.current_mode) + #ghost.update(maze, pacman) + + self.ghosts.draw(self.screen) + pygame.display.flip() + self.clock.tick(60) + + def handle_events(self): for event in pygame.event.get(): match event.type: case pygame.QUIT: - running = False + self.running = False case pygame.KEYDOWN: match event.key: case pygame.K_RIGHT: - if maze.is_wall(player.location[0] + 1, player.location[1]): + if self.maze.is_wall(self.player.location[0] + 1, self.player.location[1]): break - player.direction = PlayerDirection.DirectionRight - player.move_right() + self.player.direction = PlayerDirection.DirectionRight + self.player.move_right() case pygame.K_LEFT: - if maze.is_wall(player.location[0] - 1, player.location[1]): + if self.maze.is_wall(self.player.location[0] - 1, self.player.location[1]): break - player.direction = PlayerDirection.DirectionLeft - player.move_left() + self.player.direction = PlayerDirection.DirectionLeft + self.player.move_left() case pygame.K_UP: - if maze.is_wall(player.location[0], player.location[1] - 1): + if self.maze.is_wall(self.player.location[0], self.player.location[1] - 1): break - player.direction = PlayerDirection.DirectionUp - player.move_up() + self.player.direction = PlayerDirection.DirectionUp + self.player.move_up() case pygame.K_DOWN: - if maze.is_wall(player.location[0], player.location[1] + 1): + if self.maze.is_wall(self.player.location[0], self.player.location[1] + 1): break - player.direction = PlayerDirection.DirectionDown - player.move_down() + self.player.direction = PlayerDirection.DirectionDown + self.player.move_down() case pygame.JOYHATMOTION: - hat_x, hat_y = hat_direction = event.value - hat_timer = pygame.time.get_ticks() - hat_first_press = True + self.hat_direction = event.value + self.hat_x, self.hat_y = self.hat_direction + self.hat_timer = pygame.time.get_ticks() + self.hat_first_press = True - if event.type == pygame.USEREVENT and event.dict.get("type_name") == "JOYHATREPEAT": - print(f"Repeated hat: {event.dict['value']}") - if hat_x == 1: - if maze.is_wall(player.location[0] + 1, player.location[1]): - break - player.direction = PlayerDirection.DirectionRight - player.move_right() - elif hat_x == -1: - if maze.is_wall(player.location[0] - 1, player.location[1]): - break - player.direction = PlayerDirection.DirectionLeft - player.move_left() - elif hat_y == 1: - if maze.is_wall(player.location[0], player.location[1] - 1): - break - player.direction = PlayerDirection.DirectionUp - player.move_up() - elif hat_y == -1: - if maze.is_wall(player.location[0], player.location[1] + 1): - break - player.direction = PlayerDirection.DirectionDown - player.move_down() + if 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 + 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 + 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 + 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 + self.player.direction = PlayerDirection.DirectionDown + self.player.move_down() + # Handle hotplugging case pygame.JOYDEVICEADDED: # This event will be generated when the program starts for every # joystick, filling up the list without needing to create them manually. - joy = pygame.joystick.Joystick(event.device_index) - joysticks[joy.get_instance_id()] = PC.controller.Controllers(joy) + self.joy = pygame.joystick.Joystick(event.device_index) + self.joysticks[self.joy.get_instance_id()] = PC.controller.Controllers(self.joy) case pygame.JOYDEVICEREMOVED: - del joysticks[event.instance_id] + del self.joysticks[event.instance_id] print(f"Joystick {event.instance_id} disconnected") - match maze.collect_dot(player.location[0], player.location[1]): + match self.maze.collect_dot(self.player.location[0], self.player.location[1]): case "dot": - hud.add_points(10) + self.hud.add_points(10) case "power": - hud.add_points(50) + self.hud.add_points(50) - # In your main game loop: - handle_hat_repeat() - hud.draw(screen) - maze.draw(screen) - player.update() - player.draw() - ghost_mode_controller.update() - current_mode = ghost_mode_controller.mode - - for ghost in ghosts: - ghost.set_mode(current_mode) - #ghost.update(maze, pacman) - - ghosts.draw(screen) - pygame.display.flip() - clock.tick(60) - - if joysticks: - joysticks[joy.get_instance_id()].controllers[0].close() - - pygame.quit() - if __name__ == "__main__": - main() + pman = Game() diff --git a/repeater.py b/repeater.py new file mode 100644 index 0000000..af39e21 --- /dev/null +++ b/repeater.py @@ -0,0 +1,59 @@ +import pygame + +pygame.init() +screen = pygame.display.set_mode((640, 480)) +clock = pygame.time.Clock() + +# Constants +HAT_REPEAT_DELAY = 300 # milliseconds before first repeat +HAT_REPEAT_INTERVAL = 100 # milliseconds between repeats + +# State +hat_direction = (0, 0) +hat_timer = 0 +hat_first_press = True + +# Init joystick +pygame.joystick.init() +if pygame.joystick.get_count() > 0: + joystick = pygame.joystick.Joystick(0) + joystick.init() + +def handle_hat_repeat(): + global hat_timer, hat_first_press + now = pygame.time.get_ticks() + if hat_direction != (0, 0): + if hat_first_press: + if now - hat_timer >= HAT_REPEAT_DELAY: + hat_timer = now + hat_first_press = False + post_hat_repeat_event() + else: + if now - hat_timer >= HAT_REPEAT_INTERVAL: + hat_timer = now + post_hat_repeat_event() + +def post_hat_repeat_event(): + pygame.event.post(pygame.event.Event(pygame.USEREVENT, { + "type_name": "JOYHATREPEAT", + "value": hat_direction + })) + +running = True +while running: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + + elif event.type == pygame.JOYHATMOTION: + hat_direction = event.value + hat_timer = pygame.time.get_ticks() + hat_first_press = True + + elif event.type == pygame.USEREVENT and event.dict.get("type_name") == "JOYHATREPEAT": + print(f"Repeated hat: {event.dict['value']}") + + handle_hat_repeat() + screen.fill((0, 0, 0)) + pygame.display.flip() + clock.tick(60)