From acab63d91c73275298dff5fc20afca07f0482559 Mon Sep 17 00:00:00 2001 From: Urban Modig Date: Sat, 16 Aug 2025 18:29:44 +0200 Subject: [PATCH] Ghost WIP --- .../game/collision/GhostCollisionChecker.java | 8 ++ .../java/se/urmo/game/entities/Ghost.java | 94 +++++++++++++++++++ .../java/se/urmo/game/entities/PacMan.java | 3 +- .../java/se/urmo/game/state/PlayingState.java | 6 ++ .../java/se/urmo/game/util/Direction.java | 10 ++ 5 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 src/main/java/se/urmo/game/collision/GhostCollisionChecker.java create mode 100644 src/main/java/se/urmo/game/entities/Ghost.java diff --git a/src/main/java/se/urmo/game/collision/GhostCollisionChecker.java b/src/main/java/se/urmo/game/collision/GhostCollisionChecker.java new file mode 100644 index 0000000..2da9b1d --- /dev/null +++ b/src/main/java/se/urmo/game/collision/GhostCollisionChecker.java @@ -0,0 +1,8 @@ +package se.urmo.game.collision; + +import se.urmo.game.map.GameMap; + +public class GhostCollisionChecker { + public GhostCollisionChecker(GameMap map) { + } +} diff --git a/src/main/java/se/urmo/game/entities/Ghost.java b/src/main/java/se/urmo/game/entities/Ghost.java new file mode 100644 index 0000000..d999771 --- /dev/null +++ b/src/main/java/se/urmo/game/entities/Ghost.java @@ -0,0 +1,94 @@ +package se.urmo.game.entities; + +import se.urmo.game.collision.GhostCollisionChecker; +import se.urmo.game.main.Game; +import se.urmo.game.main.GamePanel; +import se.urmo.game.map.GameMap; +import se.urmo.game.util.Direction; +import se.urmo.game.util.LoadSave; +import se.urmo.game.util.MiscUtil; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.image.BufferedImage; + +public class Ghost { + private static final int COLLISION_BOX_SIZE = 16; + private static final int GHOST_SPEED = 1; + private static final int GHOST_MOVEMENT_UPDATE_FREQUENCY = 2; + + 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 BufferedImage COLLISION_BOX = MiscUtil.createOutlinedBox(COLLISION_BOX_SIZE, COLLISION_BOX_SIZE, Color.black, 2); + + private final Game game; + private final GhostCollisionChecker ghostCollisionChecker; + private final 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 ghostCollisionChecker) { + this.game = game; + this.ghostCollisionChecker = ghostCollisionChecker; + position = new Point(13 * 16 + 8 + GameMap.OFFSET_X, 4 * 16 + GameMap.OFFSET_Y); + loadAnimation(); + } + + private void loadAnimation() { + BufferedImage[][] image = new BufferedImage[10][4]; + + BufferedImage img = LoadSave.GetSpriteAtlas("sprites/PacManAssets-Ghosts.png"); + for (int row = 0; row < 3; row++) { + for (int col = 0; col < 4; col++) { + image[row][col] = img.getSubimage(32 * col, 32 * row, GHOST_SIZE, GHOST_SIZE); + } + } + animation = image[0]; + } + + public void draw(Graphics g) { + g.drawImage( + animation[aniIndex], + position.x - COLLISION_BOX_OFFSET, + position.y - COLLISION_BOX_OFFSET, + GHOST_SIZE, + GHOST_SIZE, null); + g.drawImage(COLLISION_BOX, position.x, position.y, COLLISION_BOX_SIZE, COLLISION_BOX_SIZE, null); + } + + public void update() { + updateAnimationTick(); + if(movementTick >= GHOST_MOVEMENT_UPDATE_FREQUENCY) { + + 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(); + + position.x += direction.dx * GHOST_SPEED; + movementTick = 0; + } else movementTick++; + } + + private void updateAnimationTick() { + if (moving) { + aniTick++; + if (aniTick >= ANIMATION_UPDATE_FREQUENCY) { + aniTick = 0; + aniIndex++; + if (aniIndex >= 3) { + aniIndex = 0; + } + + } + } + } + +} diff --git a/src/main/java/se/urmo/game/entities/PacMan.java b/src/main/java/se/urmo/game/entities/PacMan.java index acf531e..46f76bd 100644 --- a/src/main/java/se/urmo/game/entities/PacMan.java +++ b/src/main/java/se/urmo/game/entities/PacMan.java @@ -3,7 +3,6 @@ package se.urmo.game.entities; import se.urmo.game.collision.CollisionChecker; import se.urmo.game.util.Direction; import se.urmo.game.main.Game; -import se.urmo.game.main.GamePanel; import se.urmo.game.map.GameMap; import se.urmo.game.util.LoadSave; import se.urmo.game.util.MiscUtil; @@ -15,7 +14,7 @@ import java.util.Arrays; public class PacMan { public static final int PACMAN_SIZE = 32; - private static final int COLLISION_BOX_SIZE = 8; + private static final int COLLISION_BOX_SIZE = 16; private static final int COLLISION_BOX_OFFSET = (PACMAN_SIZE - COLLISION_BOX_SIZE) / 2; private final Game game; private int aniTick = 0; diff --git a/src/main/java/se/urmo/game/state/PlayingState.java b/src/main/java/se/urmo/game/state/PlayingState.java index ca31bf0..265534a 100644 --- a/src/main/java/se/urmo/game/state/PlayingState.java +++ b/src/main/java/se/urmo/game/state/PlayingState.java @@ -1,6 +1,8 @@ package se.urmo.game.state; import se.urmo.game.collision.CollisionChecker; +import se.urmo.game.collision.GhostCollisionChecker; +import se.urmo.game.entities.Ghost; import se.urmo.game.entities.PacMan; import se.urmo.game.main.Game; import se.urmo.game.map.GameMap; @@ -12,6 +14,7 @@ import java.awt.event.KeyEvent; public class PlayingState implements GameState { private final Game game; private final GameStateManager gameStateManager; + private final Ghost ghost; private PacMan pacman; private GameMap map; public PlayingState(Game game, GameStateManager gameStateManager) { @@ -19,17 +22,20 @@ public class PlayingState implements GameState { this.gameStateManager = gameStateManager; this.map = new GameMap(); this.pacman = new PacMan(game, new CollisionChecker(map)); + this.ghost = new Ghost(game, new GhostCollisionChecker(map)); } @Override public void update() { pacman.update(); + ghost.update(); } @Override public void render(Graphics2D g) { map.draw(g); pacman.draw(g); + ghost.draw(g); } @Override diff --git a/src/main/java/se/urmo/game/util/Direction.java b/src/main/java/se/urmo/game/util/Direction.java index eafd133..3dfee43 100644 --- a/src/main/java/se/urmo/game/util/Direction.java +++ b/src/main/java/se/urmo/game/util/Direction.java @@ -14,4 +14,14 @@ public enum Direction { this.dx = dx; this.dy = dy; } + + public Direction opposite() { + switch (this) { + case RIGHT: return LEFT; + case LEFT: return RIGHT; + case DOWN: return UP; + case UP: return DOWN; + default: return NONE; + } + } }