Ghost WIP

This commit is contained in:
Urban Modig
2025-08-16 18:29:44 +02:00
parent f15a01837d
commit acab63d91c
5 changed files with 119 additions and 2 deletions

View File

@ -0,0 +1,8 @@
package se.urmo.game.collision;
import se.urmo.game.map.GameMap;
public class GhostCollisionChecker {
public GhostCollisionChecker(GameMap map) {
}
}

View File

@ -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;
}
}
}
}
}

View File

@ -3,7 +3,6 @@ package se.urmo.game.entities;
import se.urmo.game.collision.CollisionChecker; import se.urmo.game.collision.CollisionChecker;
import se.urmo.game.util.Direction; import se.urmo.game.util.Direction;
import se.urmo.game.main.Game; import se.urmo.game.main.Game;
import se.urmo.game.main.GamePanel;
import se.urmo.game.map.GameMap; import se.urmo.game.map.GameMap;
import se.urmo.game.util.LoadSave; import se.urmo.game.util.LoadSave;
import se.urmo.game.util.MiscUtil; import se.urmo.game.util.MiscUtil;
@ -15,7 +14,7 @@ import java.util.Arrays;
public class PacMan { public class PacMan {
public static final int PACMAN_SIZE = 32; 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 static final int COLLISION_BOX_OFFSET = (PACMAN_SIZE - COLLISION_BOX_SIZE) / 2;
private final Game game; private final Game game;
private int aniTick = 0; private int aniTick = 0;

View File

@ -1,6 +1,8 @@
package se.urmo.game.state; package se.urmo.game.state;
import se.urmo.game.collision.CollisionChecker; 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.entities.PacMan;
import se.urmo.game.main.Game; import se.urmo.game.main.Game;
import se.urmo.game.map.GameMap; import se.urmo.game.map.GameMap;
@ -12,6 +14,7 @@ import java.awt.event.KeyEvent;
public class PlayingState implements GameState { public class PlayingState implements GameState {
private final Game game; private final Game game;
private final GameStateManager gameStateManager; private final GameStateManager gameStateManager;
private final Ghost ghost;
private PacMan pacman; private PacMan pacman;
private GameMap map; private GameMap map;
public PlayingState(Game game, GameStateManager gameStateManager) { public PlayingState(Game game, GameStateManager gameStateManager) {
@ -19,17 +22,20 @@ public class PlayingState implements GameState {
this.gameStateManager = gameStateManager; this.gameStateManager = gameStateManager;
this.map = new GameMap(); this.map = new GameMap();
this.pacman = new PacMan(game, new CollisionChecker(map)); this.pacman = new PacMan(game, new CollisionChecker(map));
this.ghost = new Ghost(game, new GhostCollisionChecker(map));
} }
@Override @Override
public void update() { public void update() {
pacman.update(); pacman.update();
ghost.update();
} }
@Override @Override
public void render(Graphics2D g) { public void render(Graphics2D g) {
map.draw(g); map.draw(g);
pacman.draw(g); pacman.draw(g);
ghost.draw(g);
} }
@Override @Override

View File

@ -14,4 +14,14 @@ public enum Direction {
this.dx = dx; this.dx = dx;
this.dy = dy; 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;
}
}
} }