diff --git a/pom.xml b/pom.xml
index ab15743..efe32ec 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,5 +13,24 @@
21
UTF-8
+
+
+ central
+ https://repo1.maven.org/maven2/
+
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.30
+ provided
+
+
+ org.slf4j
+ slf4j-simple
+ 2.0.13
+
+
\ No newline at end of file
diff --git a/src/main/java/se/urmo/game/collision/GhostCollisionChecker.java b/src/main/java/se/urmo/game/collision/GhostCollisionChecker.java
index e17b530..9a7d68e 100644
--- a/src/main/java/se/urmo/game/collision/GhostCollisionChecker.java
+++ b/src/main/java/se/urmo/game/collision/GhostCollisionChecker.java
@@ -1,5 +1,6 @@
package se.urmo.game.collision;
+import lombok.extern.slf4j.Slf4j;
import se.urmo.game.map.GameMap;
import se.urmo.game.util.Direction;
@@ -7,6 +8,7 @@ import java.awt.Point;
import java.util.Collections;
import java.util.List;
+@Slf4j
public class GhostCollisionChecker {
private final GameMap map;
@@ -32,16 +34,20 @@ public class GhostCollisionChecker {
default -> Collections.EMPTY_LIST;
};
- System.out.println( direction + " bounderies for " + position + " are " + bounderies);
+ 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)) {
+ if (! map.isSolid(normalizedBoundaries)) {
+ log.debug("{} is open", direction);
return normalizePosition(direction, position, agent_width, agent_height);
+ }{
+ log.debug("{} is blocked", direction);
+ return null;
}
- return null; // Blocked
+ // Blocked
}
public Point normalizePosition(Direction dir, Point pos, int agent_width, int agent_height) {
@@ -57,9 +63,9 @@ public class GhostCollisionChecker {
return new Point(x, y);
}
- public List isIntersection(Point position) {
- List intersection = map.isIntersection(position);
- System.out.println("Possible travel directions: " + intersection);
+ public List calculateDirectionAlternatives(Point position) {
+ List intersection = map.directionAlternatives(position);
+ log.info("Possible travel directions: {}", intersection);
return intersection;
}
}
diff --git a/src/main/java/se/urmo/game/entities/BlinkyStrategy.java b/src/main/java/se/urmo/game/entities/BlinkyStrategy.java
new file mode 100644
index 0000000..d824520
--- /dev/null
+++ b/src/main/java/se/urmo/game/entities/BlinkyStrategy.java
@@ -0,0 +1,10 @@
+package se.urmo.game.entities;
+
+import java.awt.Point;
+
+public class BlinkyStrategy implements GhostStrategy {
+ @Override
+ public Point chooseTarget(PacMan pacman, Ghost self, Ghost blinky) {
+ return pacman.getTilePosition();
+ }
+}
diff --git a/src/main/java/se/urmo/game/entities/Ghost.java b/src/main/java/se/urmo/game/entities/Ghost.java
index bfcd150..a10a3ef 100644
--- a/src/main/java/se/urmo/game/entities/Ghost.java
+++ b/src/main/java/se/urmo/game/entities/Ghost.java
@@ -1,5 +1,6 @@
package se.urmo.game.entities;
+import lombok.extern.slf4j.Slf4j;
import se.urmo.game.collision.GhostCollisionChecker;
import se.urmo.game.main.Game;
import se.urmo.game.map.GameMap;
@@ -13,6 +14,7 @@ import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.List;
+@Slf4j
public class Ghost {
private static final int COLLISION_BOX_SIZE = 16;
private static final int GHOST_SPEED = 1;
@@ -25,19 +27,20 @@ public class Ghost {
private final Game game;
private final GhostCollisionChecker collisionChecker;
+ private final GhostStrategy strategy;
private Point position;
private boolean moving = true;
private int aniTick = 0;
private int aniIndex = 0;
private BufferedImage[] animation;
- private Direction direction = Direction.LEFT;
private int movementTick = 0;
public Ghost(Game game, GhostCollisionChecker collisionChecker, GhostStrategy strategy) {
this.game = game;
this.collisionChecker = collisionChecker;
+ this.strategy = strategy;
position = new Point(13 * 16 + 8 + GameMap.OFFSET_X, 4 * 16 + GameMap.OFFSET_Y);
loadAnimation();
}
@@ -64,36 +67,25 @@ public class Ghost {
g.drawImage(COLLISION_BOX, position.x, position.y, COLLISION_BOX_SIZE, COLLISION_BOX_SIZE, null);
}
- public void update() {
+ public void update(PacMan pacman) {
updateAnimationTick();
+ updatePosition(pacman);
+ }
+
+ private void updatePosition(PacMan pacman) {
if(movementTick >= GHOST_MOVEMENT_UPDATE_FREQUENCY) {
- // if intersection - decide direction
- // else if direction isPassible
- List i = collisionChecker.isIntersection(position);
- if(!i.isEmpty()){
- // Change direction
- if(i.contains(Direction.DOWN)) direction = Direction.DOWN;
- else if(i.contains(Direction.RIGHT)) direction = Direction.RIGHT;
- else if(i.contains(Direction.UP)) direction = Direction.UP;
- else direction = Direction.LEFT;
+ log.info("Evaluating possible directions");
+ Direction intendedDirection = chooseDirection(
+ collisionChecker.calculateDirectionAlternatives(position),
+ strategy.chooseTarget(pacman, null, null));
- }
- //Point target = strategy.chooseTarget(pacman, this, blinky);
+ log.info("selecting direction {}", intendedDirection);
+ Point newPosition = new Point(
+ position.x += intendedDirection.dx * GHOST_SPEED,
+ position.y += intendedDirection.dy * GHOST_SPEED);
- Point newPosition = switch (direction){
- case RIGHT -> new Point(position.x += GHOST_SPEED, position.y);
- case LEFT -> new Point(position.x -= GHOST_SPEED, position.y);
- case DOWN -> new Point(position.x, position.y += GHOST_SPEED);
- case UP -> new Point(position.x, position.y -= GHOST_SPEED);
- default -> throw new IllegalStateException("Illegal direction");
- };
-
- Point destination = collisionChecker.getValidDestination(direction, newPosition, GHOST_SIZE, GHOST_SIZE);
-
-// if (position.x + direction.dx * GHOST_SPEED < GameMap.OFFSET_X) direction = direction.opposite();
-// if (position.x + GHOST_SIZE + (direction.dx * GHOST_SPEED) > GamePanel.SCREEN_WIDTH - GameMap.OFFSET_X)
-// direction = direction.opposite();
+ Point destination = collisionChecker.getValidDestination(intendedDirection, newPosition, COLLISION_BOX_SIZE, COLLISION_BOX_SIZE);
if(destination != null) {
position = destination;
diff --git a/src/main/java/se/urmo/game/entities/GhostStrategy.java b/src/main/java/se/urmo/game/entities/GhostStrategy.java
new file mode 100644
index 0000000..6635f01
--- /dev/null
+++ b/src/main/java/se/urmo/game/entities/GhostStrategy.java
@@ -0,0 +1,7 @@
+package se.urmo.game.entities;
+
+import java.awt.Point;
+
+public interface GhostStrategy {
+ Point chooseTarget(PacMan pacman, Ghost self, Ghost blinky);
+}
diff --git a/src/main/java/se/urmo/game/entities/PacMan.java b/src/main/java/se/urmo/game/entities/PacMan.java
index 46f76bd..8bbd812 100644
--- a/src/main/java/se/urmo/game/entities/PacMan.java
+++ b/src/main/java/se/urmo/game/entities/PacMan.java
@@ -109,4 +109,8 @@ public class PacMan {
public void setDirection(Direction direction) {
this.direction = direction;
}
+
+ public Point getTilePosition() {
+ return position;
+ }
}
diff --git a/src/main/java/se/urmo/game/map/GameMap.java b/src/main/java/se/urmo/game/map/GameMap.java
index 9bdf913..77a401e 100644
--- a/src/main/java/se/urmo/game/map/GameMap.java
+++ b/src/main/java/se/urmo/game/map/GameMap.java
@@ -1,5 +1,6 @@
package se.urmo.game.map;
+import lombok.extern.slf4j.Slf4j;
import se.urmo.game.main.GamePanel;
import se.urmo.game.util.Direction;
import se.urmo.game.util.LoadSave;
@@ -13,6 +14,7 @@ import java.util.Objects;
import java.util.stream.IntStream;
import java.util.stream.Stream;
+@Slf4j
public class GameMap {
public static final int MAP_TILESIZE = 16;// 16px from left
public static final int OFFSET_Y = 7 * MAP_TILESIZE; // 160px from top
@@ -169,22 +171,28 @@ public class GameMap {
if(tile.getValue() == 0) tile.setImage(null);
}
- public List isIntersection(Point position) {
+ public List directionAlternatives(Point position) {
int row = (position.y - OFFSET_Y) / MAP_TILESIZE;
int col = (position.x - OFFSET_X) / MAP_TILESIZE;
record DirectionCheck(int rowOffset, int colOffset, Direction direction) {}
-
+ log.debug("At [{}][{}]", row, col);
return Stream.of(
new DirectionCheck(0, 1, Direction.RIGHT),
new DirectionCheck(0, -1, Direction.LEFT),
new DirectionCheck(1, 0, Direction.DOWN),
new DirectionCheck(-1, 0, Direction.UP)
)
- .filter(dc -> !mapData[row + dc.rowOffset][col + dc.colOffset].isSolid())
+ .filter(dc -> {
+ int r = row + dc.rowOffset;
+ int c = col + dc.colOffset;
+ MapTile mapTile = mapData[r][c];
+ boolean solid = mapTile.isSolid();
+ log.debug("[{}][{}] {} is {} ({})", r, c, dc.direction, solid ? "solid" : " not solid", mapTile.getValue());
+ return !solid;
+ })
.map(DirectionCheck::direction)
.toList();
-
}
public boolean isSolid(List points) {
@@ -196,7 +204,7 @@ public class GameMap {
int col = (x - OFFSET_X) / MAP_TILESIZE;
MapTile mapTile = mapData[row][col];
boolean solid = mapTile.isSolid();
- //System.out.println("["+row+"]["+col+"] is " + (solid?"solid":" not solid") + " (" + mapTile.getValue() + ")");
+ log.debug("["+row+"]["+col+"] is " + (solid?"solid":" not solid") + " (" + mapTile.getValue() + ")");
return solid;
}
}
diff --git a/src/main/java/se/urmo/game/map/MapTile.java b/src/main/java/se/urmo/game/map/MapTile.java
index 402359f..e769faf 100644
--- a/src/main/java/se/urmo/game/map/MapTile.java
+++ b/src/main/java/se/urmo/game/map/MapTile.java
@@ -1,7 +1,12 @@
package se.urmo.game.map;
+import lombok.Getter;
+import lombok.Setter;
+
import java.awt.image.BufferedImage;
+@Getter
+@Setter
public class MapTile {
private final int value;
private BufferedImage image;
@@ -11,14 +16,10 @@ public class MapTile {
public MapTile(BufferedImage image, int value) {
this.value = value;
this.image = image;
- this.solid = value != 0;
+ this.solid = value != 0 && value != 99;
this.collisionMask = value != 0 ? createCollisionMask(image) : null;
}
- public boolean[][] getCollisionMask() {
- return collisionMask;
- }
-
private boolean[][] createCollisionMask(BufferedImage img) {
if(img == null) return null;
int w = img.getWidth();
@@ -33,19 +34,4 @@ public class MapTile {
return mask;
}
- public BufferedImage getImage() {
- return this.image;
- }
-
- public boolean isSolid() {
- return this.solid;
- }
-
- public void setImage(BufferedImage img) {
- this.image = img;
- }
-
- public int getValue() {
- return this.value;
- }
}
diff --git a/src/main/java/se/urmo/game/state/PlayingState.java b/src/main/java/se/urmo/game/state/PlayingState.java
index f7dcc43..0b5ba85 100644
--- a/src/main/java/se/urmo/game/state/PlayingState.java
+++ b/src/main/java/se/urmo/game/state/PlayingState.java
@@ -1,7 +1,9 @@
package se.urmo.game.state;
+import lombok.Getter;
import se.urmo.game.collision.CollisionChecker;
import se.urmo.game.collision.GhostCollisionChecker;
+import se.urmo.game.entities.BlinkyStrategy;
import se.urmo.game.entities.Ghost;
import se.urmo.game.entities.PacMan;
import se.urmo.game.main.Game;
@@ -16,19 +18,20 @@ public class PlayingState implements GameState {
private final GameStateManager gameStateManager;
private final Ghost ghost;
private PacMan pacman;
+ @Getter
private GameMap map;
public PlayingState(Game game, GameStateManager gameStateManager) {
this.game = game;
this.gameStateManager = gameStateManager;
this.map = new GameMap();
this.pacman = new PacMan(game, new CollisionChecker(map));
- this.ghost = new Ghost(game, new GhostCollisionChecker(map), null);
+ this.ghost = new Ghost(game, new GhostCollisionChecker(map), new BlinkyStrategy());
}
@Override
public void update() {
pacman.update();
- ghost.update();
+ ghost.update(pacman);
}
@Override
@@ -58,8 +61,4 @@ public class PlayingState implements GameState {
pacman.setMoving(false);
pacman.setDirection(Direction.NONE);
}
-
- public GameMap getMap() {
- return map;
- }
}
diff --git a/src/main/resources/simplelogger.properties b/src/main/resources/simplelogger.properties
new file mode 100644
index 0000000..eafa2b0
--- /dev/null
+++ b/src/main/resources/simplelogger.properties
@@ -0,0 +1 @@
+org.slf4j.simpleLogger.defaultLogLevel=debug
\ No newline at end of file