package se.urmo.game.state; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import se.urmo.game.collision.GhostCollisionChecker; import se.urmo.game.entities.BlinkyStrategy; import se.urmo.game.entities.ClydeStrategy; import se.urmo.game.entities.Ghost; import se.urmo.game.entities.GhostMode; import se.urmo.game.entities.InkyStrategy; import se.urmo.game.entities.PacMan; import se.urmo.game.entities.PinkyStrategy; import se.urmo.game.entities.ScatterToBottomLeft; import se.urmo.game.entities.ScatterToBottomRight; import se.urmo.game.entities.ScatterToTopLeft; import se.urmo.game.entities.ScatterToTopRight; import se.urmo.game.map.GameMap; import se.urmo.game.util.LoadSave; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; @Slf4j public class GhostManager { public static final int SPRITE_SHEET_ROWS = 10; public static final int MAX_SPRITE_FRAMES = 4; @Getter private final List ghosts = new ArrayList<>(); private BufferedImage[][] image; private GhostMode globalMode; private long lastModeSwitchTime; private int phaseIndex = 0; // cycle in milliseconds: {scatter, chase, scatter, chase, ...} private final int[] cycleDurations = { 7000, 20000, // scatter 7s, chase 20s 7000, 20000, // scatter 7s, chase 20s 5000, 20000, // scatter 5s, chase 20s 5000, Integer.MAX_VALUE // scatter 5s, then chase forever }; public GhostManager(GhostCollisionChecker ghostCollisionChecker) { loadAnimation(); // Create ghosts with their strategies Ghost blinky = new Ghost(ghostCollisionChecker, new BlinkyStrategy(), new ScatterToTopRight(), image[0]); ghosts.add(blinky); ghosts.add(new Ghost(ghostCollisionChecker, new PinkyStrategy(),new ScatterToTopLeft(), image[2])); ghosts.add(new Ghost(ghostCollisionChecker,new InkyStrategy(blinky), new ScatterToBottomRight(), image[1])); ghosts.add(new Ghost(ghostCollisionChecker, new ClydeStrategy(), new ScatterToBottomLeft(), image[3])); setMode(GhostMode.CHASE); } private void loadAnimation() { image = new BufferedImage[SPRITE_SHEET_ROWS][MAX_SPRITE_FRAMES]; BufferedImage img = LoadSave.GetSpriteAtlas("sprites/PacManAssets-Ghosts.png"); for (int row = 0; row < SPRITE_SHEET_ROWS; row++) { for (int col = 0; col < MAX_SPRITE_FRAMES; col++) { image[row][col] = img.getSubimage(Ghost.GHOST_SIZE * col, Ghost.GHOST_SIZE * row, Ghost.GHOST_SIZE, Ghost.GHOST_SIZE); } } } public void setMode(GhostMode mode) { this.globalMode = mode; log.info("Mode changed to {}", globalMode); for (Ghost g : ghosts) { g.setMode(mode); } } public void update(PacMan pacman, GameMap map) { long now = System.currentTimeMillis(); if (phaseIndex < cycleDurations.length) { int duration = cycleDurations[phaseIndex]; if (now - lastModeSwitchTime >= duration) { phaseIndex++; if (phaseIndex < cycleDurations.length) { GhostMode newMode = (phaseIndex % 2 == 0) ? GhostMode.SCATTER : GhostMode.CHASE; setMode(newMode); } lastModeSwitchTime = now; } } for (Ghost g : ghosts) { g.update(pacman, map); } } public void draw(Graphics2D g) { for (Ghost ghost : ghosts) { ghost.draw(g); } } }