Added remaining ghosts incl. movment-strategies

This commit is contained in:
Urban Modig
2025-08-20 15:26:06 +02:00
parent 9f316e5b43
commit 8e546fe942
13 changed files with 129 additions and 32 deletions

View File

@ -6,7 +6,7 @@ import java.awt.Point;
public class BlinkyStrategy implements GhostStrategy {
@Override
public Point chooseTarget(PacMan pacman, GameMap map) {
public Point chooseTarget(Ghost ghost, PacMan pacman, GameMap map) {
return pacman.getTilePosition();
}
}

View File

@ -0,0 +1,21 @@
package se.urmo.game.entities;
import se.urmo.game.map.GameMap;
import java.awt.Point;
public class ClydeStrategy implements GhostStrategy {
@Override
public Point chooseTarget(Ghost clyde, PacMan pacman, GameMap map) {
Point pacTile = pacman.getTilePosition();
Point clydeTile = clyde.getPosition(); // ghosts current tile
double distance = pacTile.distance(clydeTile);
if (distance > 8) {
return pacTile; // chase Pac-Man
} else {
return new Point(0, map.getHeight() - 1); // retreat to corner
}
}
}

View File

@ -1,5 +1,6 @@
package se.urmo.game.entities;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import se.urmo.game.collision.GhostCollisionChecker;
import se.urmo.game.map.GameMap;
@ -11,8 +12,6 @@ import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@ -29,6 +28,7 @@ public class Ghost {
private final GhostCollisionChecker collisionChecker;
private final GhostStrategy chaseStrategy;
@Getter
private Point position;
private boolean moving = true;
@ -81,7 +81,7 @@ public class Ghost {
prevDirection = direction;
direction = chooseDirection(
prioritize(collisionChecker.calculateDirectionAlternatives(position)),
currentStrategy.chooseTarget(pacman, map));
currentStrategy.chooseTarget(this, pacman, map));
log.info("selecting direction {}", direction);
}
@ -167,4 +167,5 @@ public class Ghost {
case EATEN -> currentStrategy = null;
}
}
}

View File

@ -5,5 +5,5 @@ import se.urmo.game.map.GameMap;
import java.awt.Point;
public interface GhostStrategy {
Point chooseTarget(PacMan pacman, GameMap map);
Point chooseTarget(Ghost ghost, PacMan pacman, GameMap map);
}

View File

@ -0,0 +1,42 @@
package se.urmo.game.entities;
import se.urmo.game.map.GameMap;
import se.urmo.game.util.Direction;
import java.awt.Point;
public class InkyStrategy implements GhostStrategy {
private final Ghost blinky;
public InkyStrategy(Ghost blinky) {
this.blinky = blinky;
}
@Override
public Point chooseTarget(Ghost ghost, PacMan pacman, GameMap map) {
// 1. Two tiles ahead of pacman
Direction pacmanDir = pacman.getDirection();
Point pacmanPos = pacman.getTilePosition();
Point ahead = switch (pacmanDir){
case RIGHT -> new Point(pacmanPos.x + 8 * GameMap.MAP_TILESIZE, pacmanPos.y);
case LEFT -> new Point(pacmanPos.x - 8 * GameMap.MAP_TILESIZE, pacmanPos.y);
case DOWN -> new Point(pacmanPos.x, pacmanPos.y + 8 * GameMap.MAP_TILESIZE);
case UP -> new Point(pacmanPos.x, pacmanPos.y - 8 * GameMap.MAP_TILESIZE);
case NONE -> pacmanPos;
};
// 2. Vector from blinky to that tile
Point blinkyPos = blinky.getPosition();
int vx = ahead.x - blinkyPos.x;
int vy = ahead.y - blinkyPos.y;
// 3. Double the vector
Point target = new Point(
blinkyPos.x + 2 * vx,
blinkyPos.y + 2 * vy
);
return target;
// (Optional: clamp inside map boundaries)
//return map.clampToBounds(target);
}
}

View File

@ -7,14 +7,14 @@ import java.awt.Point;
public class PinkyStrategy implements GhostStrategy{
@Override
public Point chooseTarget(PacMan pacman, GameMap map) {
public Point chooseTarget(Ghost ghost, PacMan pacman, GameMap map) {
Direction pacmanDir = pacman.getDirection();
Point pacmanPos = pacman.getTilePosition();
return switch (pacmanDir){
case RIGHT -> new Point(pacmanPos.x + 4 * GameMap.MAP_TILESIZE, pacmanPos.y);
case LEFT -> new Point(pacmanPos.x - 4 * GameMap.MAP_TILESIZE, pacmanPos.y);
case DOWN -> new Point(pacmanPos.x, pacmanPos.y + 4 * GameMap.MAP_TILESIZE);
case UP -> new Point(pacmanPos.x, pacmanPos.y - 4 * GameMap.MAP_TILESIZE);
case RIGHT -> new Point(pacmanPos.x + 8 * GameMap.MAP_TILESIZE, pacmanPos.y);
case LEFT -> new Point(pacmanPos.x - 8 * GameMap.MAP_TILESIZE, pacmanPos.y);
case DOWN -> new Point(pacmanPos.x, pacmanPos.y + 8 * GameMap.MAP_TILESIZE);
case UP -> new Point(pacmanPos.x, pacmanPos.y - 8 * GameMap.MAP_TILESIZE);
case NONE -> pacmanPos;
};
}

View File

@ -0,0 +1,12 @@
package se.urmo.game.entities;
import se.urmo.game.map.GameMap;
import java.awt.Point;
public class ScatterToBottomLeft implements GhostStrategy {
@Override
public Point chooseTarget(Ghost ghost, PacMan pacman, GameMap map) {
return new Point(GameMap.OFFSET_X, (map.columns() * GameMap.MAP_TILESIZE) + GameMap.OFFSET_Y);
}
}

View File

@ -0,0 +1,12 @@
package se.urmo.game.entities;
import se.urmo.game.map.GameMap;
import java.awt.Point;
public class ScatterToBottomRight implements GhostStrategy {
@Override
public Point chooseTarget(Ghost ghost, PacMan pacman, GameMap map) {
return new Point(map.getHeight() - 1, map.getHeight() - 1);
}
}

View File

@ -0,0 +1,13 @@
package se.urmo.game.entities;
import se.urmo.game.map.GameMap;
import java.awt.Point;
public class ScatterToTopLeft implements GhostStrategy {
@Override
public Point chooseTarget(Ghost ghost, PacMan pacman, GameMap map) {
return new Point(GameMap.OFFSET_X, GameMap.OFFSET_Y);
}
}

View File

@ -6,7 +6,7 @@ import java.awt.Point;
public class ScatterToTopRight implements GhostStrategy{
@Override
public Point chooseTarget(PacMan pacman, GameMap map) {
return new Point((map.columns() -1) * GameMap.MAP_TILESIZE, 0);
public Point chooseTarget(Ghost ghost, PacMan pacman, GameMap map) {
return new Point((map.columns() -1) * GameMap.MAP_TILESIZE + GameMap.OFFSET_X, 0);
}
}