diff --git a/src/main/java/se/urmo/game/collision/GhostCollisionChecker.java b/src/main/java/se/urmo/game/collision/GhostCollisionChecker.java index 9a7d68e..91489a2 100644 --- a/src/main/java/se/urmo/game/collision/GhostCollisionChecker.java +++ b/src/main/java/se/urmo/game/collision/GhostCollisionChecker.java @@ -16,56 +16,15 @@ public class GhostCollisionChecker { this.map = map; } - public Point getValidDestination(Direction direction, Point position, int agent_width, int agent_height) { - - List bounderies = switch (direction) { - case RIGHT -> List.of( - new Point(position.x + agent_width, position.y), // TOPRIGHT - new Point(position.x + agent_width, position.y + agent_height)); // BOTTOMRIGHT - case LEFT -> List.of( - position, // TOPLEFT - new Point(position.x, position.y + agent_height)); // BOTTOMLEFT - case UP -> List.of( - position, // TOPLEFT - new Point(position.x + agent_width, position.y)); // TOPRIGHT - case DOWN -> List.of( - new Point(position.x, position.y + agent_height), // BOTTOMLEFT - new Point(position.x + agent_width, position.y + agent_height)); // BOTTOMRIGHT - default -> Collections.EMPTY_LIST; - }; - - log.debug("{} bounderies for {} are {}", direction, position, bounderies); - - List normalizedBoundaries = bounderies.stream() - .map(p -> normalizePosition(direction, p, agent_width, agent_height)) - .toList(); - - if (! map.isSolid(normalizedBoundaries)) { - log.debug("{} is open", direction); - return normalizePosition(direction, position, agent_width, agent_height); - }{ - log.debug("{} is blocked", direction); - return null; - } - // Blocked - } - - public Point normalizePosition(Direction dir, Point pos, int agent_width, int agent_height) { - int x = pos.x; - int y = pos.y; - int width = map.getWidth(); - int height = map.getHeight(); - - // tunnel - if (x < GameMap.OFFSET_X) x = width - agent_width - GameMap.OFFSET_X; // right - if (x >= (width - GameMap.OFFSET_X)) x = GameMap.OFFSET_X; // left - - return new Point(x, y); - } - public List calculateDirectionAlternatives(Point position) { List intersection = map.directionAlternatives(position); log.info("Possible travel directions: {}", intersection); return intersection; } + + public Point canMoveTo(Direction dir, Point pos) { + Point pp = new Point(pos.x + dir.dx * GameMap.MAP_TILESIZE/2, pos.y + dir.dy * GameMap.MAP_TILESIZE/2); + + return ! map.isSolid(pp.x, pp.y) ? pos : null; + } } diff --git a/src/main/java/se/urmo/game/entities/Ghost.java b/src/main/java/se/urmo/game/entities/Ghost.java index a10a3ef..5deb5e0 100644 --- a/src/main/java/se/urmo/game/entities/Ghost.java +++ b/src/main/java/se/urmo/game/entities/Ghost.java @@ -22,7 +22,7 @@ public class Ghost { private static int GHOST_SIZE = 32; private static final int ANIMATION_UPDATE_FREQUENCY = 25; - private static final int COLLISION_BOX_OFFSET = (GHOST_SIZE - COLLISION_BOX_SIZE) / 2; + private static final int COLLISION_BOX_OFFSET = COLLISION_BOX_SIZE / 2; private static final BufferedImage COLLISION_BOX = MiscUtil.createOutlinedBox(COLLISION_BOX_SIZE, COLLISION_BOX_SIZE, Color.black, 2); private final Game game; @@ -41,7 +41,9 @@ public class Ghost { this.game = game; this.collisionChecker = collisionChecker; this.strategy = strategy; - position = new Point(13 * 16 + 8 + GameMap.OFFSET_X, 4 * 16 + GameMap.OFFSET_Y); + position = new Point( + 13 * GameMap.MAP_TILESIZE + (GameMap.MAP_TILESIZE / 2) + GameMap.OFFSET_X, + 4 * GameMap.MAP_TILESIZE + (GameMap.MAP_TILESIZE / 2) + GameMap.OFFSET_Y); loadAnimation(); } @@ -60,11 +62,15 @@ public class Ghost { public void draw(Graphics g) { g.drawImage( animation[aniIndex], - position.x - COLLISION_BOX_OFFSET, - position.y - COLLISION_BOX_OFFSET, + position.x - GHOST_SIZE / 2, + position.y - GHOST_SIZE / 2, GHOST_SIZE, GHOST_SIZE, null); - g.drawImage(COLLISION_BOX, position.x, position.y, COLLISION_BOX_SIZE, COLLISION_BOX_SIZE, null); + g.drawImage(COLLISION_BOX, + position.x - COLLISION_BOX_OFFSET, + position.y - COLLISION_BOX_OFFSET, + COLLISION_BOX_SIZE, + COLLISION_BOX_SIZE, null); } public void update(PacMan pacman) { @@ -74,6 +80,12 @@ public class Ghost { private void updatePosition(PacMan pacman) { if(movementTick >= GHOST_MOVEMENT_UPDATE_FREQUENCY) { + if(!isAlligned(position)){ + position = align(position); + log.debug("Aligned: {}", position); + return; + } + log.info("Evaluating possible directions"); Direction intendedDirection = chooseDirection( collisionChecker.calculateDirectionAlternatives(position), @@ -82,11 +94,10 @@ public class Ghost { log.info("selecting direction {}", intendedDirection); Point newPosition = new Point( - position.x += intendedDirection.dx * GHOST_SPEED, - position.y += intendedDirection.dy * GHOST_SPEED); - - Point destination = collisionChecker.getValidDestination(intendedDirection, newPosition, COLLISION_BOX_SIZE, COLLISION_BOX_SIZE); + position.x + intendedDirection.dx * GHOST_SPEED, + position.y + intendedDirection.dy * GHOST_SPEED); + Point destination = collisionChecker.canMoveTo(intendedDirection, newPosition); if(destination != null) { position = destination; } @@ -94,8 +105,19 @@ public class Ghost { } else movementTick++; } + private boolean isAlligned(Point pos) { + int row = pos.x % GameMap.MAP_TILESIZE; + int col = pos.y % GameMap.MAP_TILESIZE; + return row == GameMap.MAP_TILESIZE/2 || col == GameMap.MAP_TILESIZE /2; + } + private Point align(Point point){ + int row = point.x / GameMap.MAP_TILESIZE; + int col = point.y / GameMap.MAP_TILESIZE; + return new Point(row * GameMap.MAP_TILESIZE + GameMap.MAP_TILESIZE /2, col * GameMap.MAP_TILESIZE + GameMap.MAP_TILESIZE /2); + } + private Direction chooseDirection(List options, Point target) { - Direction best = options.get(0); + Direction best = options.getFirst(); double bestDist = Double.MAX_VALUE; for (Direction d : options) { diff --git a/src/main/java/se/urmo/game/map/GameMap.java b/src/main/java/se/urmo/game/map/GameMap.java index 77a401e..ec222bf 100644 --- a/src/main/java/se/urmo/game/map/GameMap.java +++ b/src/main/java/se/urmo/game/map/GameMap.java @@ -199,7 +199,7 @@ public class GameMap { return points.stream().allMatch(p -> isSolid(p.x, p.y)); } - private boolean isSolid(int x, int y) { + public boolean isSolid(int x, int y) { int row = (y - OFFSET_Y) / MAP_TILESIZE; int col = (x - OFFSET_X) / MAP_TILESIZE; MapTile mapTile = mapData[row][col];