From aac651cf93daacc9ae531fb6fd74a34966beef6d Mon Sep 17 00:00:00 2001 From: jzitnik-dev Date: Thu, 22 Jan 2026 16:11:16 +0100 Subject: [PATCH] refactor: Reworked collision system --- .../java/cz/jzitnik/config/Debugging.java | 4 ++-- .../handlers/PlayerMoveEventHandler.java | 8 ++++---- .../java/cz/jzitnik/game/GameRoomPart.java | 19 ++++++++++++++----- src/main/java/cz/jzitnik/game/Player.java | 1 + .../java/cz/jzitnik/game/mobs/DialogMob.java | 9 +++++---- .../cz/jzitnik/game/mobs/HittableMob.java | 5 +++-- .../jzitnik/game/mobs/HittableMobDrops.java | 9 +++++---- .../jzitnik/game/mobs/HittableMobNoDrops.java | 5 +++-- src/main/java/cz/jzitnik/game/mobs/Mob.java | 8 ++++++-- .../mobs/tasks/MobFollowingPlayerTask.java | 2 +- .../game/mobs/tasks/utils/AStarAlg.java | 13 ++++++++----- .../java/cz/jzitnik/game/setup/GameSetup.java | 8 +++++++- .../cz/jzitnik/game/setup/enemies/Pepa.java | 8 +++++++- .../cz/jzitnik/game/setup/enemies/Zombie.java | 9 ++++++++- .../cz/jzitnik/game/setup/rooms/MainRoom.java | 4 ++-- .../java/cz/jzitnik/game/utils/RoomCords.java | 9 +++++++-- .../java/cz/jzitnik/utils/RerenderUtils.java | 4 ++-- 17 files changed, 85 insertions(+), 40 deletions(-) diff --git a/src/main/java/cz/jzitnik/config/Debugging.java b/src/main/java/cz/jzitnik/config/Debugging.java index 1f46f8b..8ae4227 100644 --- a/src/main/java/cz/jzitnik/config/Debugging.java +++ b/src/main/java/cz/jzitnik/config/Debugging.java @@ -6,6 +6,6 @@ import lombok.Getter; @Getter @Config public class Debugging { - private final boolean renderColliders = false; - private final boolean renderPlayerCollider = false; + private final boolean renderColliders = true; + private final boolean renderPlayerCollider = true; } diff --git a/src/main/java/cz/jzitnik/events/handlers/PlayerMoveEventHandler.java b/src/main/java/cz/jzitnik/events/handlers/PlayerMoveEventHandler.java index f319129..c1041c9 100644 --- a/src/main/java/cz/jzitnik/events/handlers/PlayerMoveEventHandler.java +++ b/src/main/java/cz/jzitnik/events/handlers/PlayerMoveEventHandler.java @@ -87,7 +87,7 @@ public class PlayerMoveEventHandler extends AbstractEventHandler { @@ -98,7 +98,7 @@ public class PlayerMoveEventHandler extends AbstractEventHandler { @@ -109,7 +109,7 @@ public class PlayerMoveEventHandler extends AbstractEventHandler { @@ -120,7 +120,7 @@ public class PlayerMoveEventHandler extends AbstractEventHandler= start.getX() && - cords.getX() <= end.getX() && - cords.getY() >= start.getY() && - cords.getY() <= end.getY(); + return cords.getX() >= start.getX() && + cords.getX() <= end.getX() && + cords.getY() >= start.getY() && + cords.getY() <= end.getY(); + } + + /** + * Checks if this GameRoomPart overlaps with another. + */ + public boolean isOverlapping(GameRoomPart other) { + return start.getX() <= other.getEnd().getX() && + end.getX() >= other.getStart().getX() && + start.getY() <= other.getEnd().getY() && + end.getY() >= other.getStart().getY(); } } diff --git a/src/main/java/cz/jzitnik/game/Player.java b/src/main/java/cz/jzitnik/game/Player.java index e502d9e..2f011c0 100644 --- a/src/main/java/cz/jzitnik/game/Player.java +++ b/src/main/java/cz/jzitnik/game/Player.java @@ -29,6 +29,7 @@ public class Player { private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); private final RoomCords playerCords; + private final GameRoomPart collider; private final GameItem[] inventory = new GameItem[Inventory.ITEMS_X * Inventory.ITEMS_Y]; @Setter private PlayerRotation playerRotation = PlayerRotation.FRONT; diff --git a/src/main/java/cz/jzitnik/game/mobs/DialogMob.java b/src/main/java/cz/jzitnik/game/mobs/DialogMob.java index 0ea2c2d..6287175 100644 --- a/src/main/java/cz/jzitnik/game/mobs/DialogMob.java +++ b/src/main/java/cz/jzitnik/game/mobs/DialogMob.java @@ -2,6 +2,7 @@ package cz.jzitnik.game.mobs; import cz.jzitnik.annotations.injectors.InjectDependency; import cz.jzitnik.annotations.injectors.InjectState; +import cz.jzitnik.game.GameRoomPart; import cz.jzitnik.game.dialog.Dialog; import cz.jzitnik.game.utils.RoomCords; import cz.jzitnik.states.DialogState; @@ -16,13 +17,13 @@ import java.awt.image.BufferedImage; public abstract class DialogMob extends Mob { protected Dialog dialog; - public DialogMob(BufferedImage texture, RoomTask[] tasks, RoomCords cords, Dialog dialog) { - super(texture, tasks, cords); + public DialogMob(BufferedImage texture, RoomTask[] tasks, RoomCords cords, GameRoomPart collider, Dialog dialog) { + super(texture, tasks, cords, collider); this.dialog = dialog; } - public DialogMob(BufferedImage texture, RoomTask task, RoomCords cords, Dialog dialog) { - super(texture, task, cords); + public DialogMob(BufferedImage texture, RoomTask task, RoomCords cords, GameRoomPart collider, Dialog dialog) { + super(texture, task, cords, collider); this.dialog = dialog; } diff --git a/src/main/java/cz/jzitnik/game/mobs/HittableMob.java b/src/main/java/cz/jzitnik/game/mobs/HittableMob.java index 80d8eea..17f2997 100644 --- a/src/main/java/cz/jzitnik/game/mobs/HittableMob.java +++ b/src/main/java/cz/jzitnik/game/mobs/HittableMob.java @@ -3,6 +3,7 @@ package cz.jzitnik.game.mobs; import cz.jzitnik.annotations.injectors.InjectDependency; import cz.jzitnik.annotations.injectors.InjectState; import cz.jzitnik.events.RerenderPart; +import cz.jzitnik.game.GameRoomPart; import cz.jzitnik.game.GameState; import cz.jzitnik.game.utils.RoomCords; import cz.jzitnik.utils.DependencyManager; @@ -67,8 +68,8 @@ public abstract class HittableMob extends Mob { @InjectDependency private RoomTaskScheduler roomTaskScheduler; - public HittableMob(BufferedImage texture, RoomTask task, RoomCords cords, int initialHealth) { - super(texture, task, cords); + public HittableMob(BufferedImage texture, RoomTask task, RoomCords cords, GameRoomPart collider, int initialHealth) { + super(texture, task, cords, collider); health = initialHealth; } diff --git a/src/main/java/cz/jzitnik/game/mobs/HittableMobDrops.java b/src/main/java/cz/jzitnik/game/mobs/HittableMobDrops.java index 24b2a0d..cb2f429 100644 --- a/src/main/java/cz/jzitnik/game/mobs/HittableMobDrops.java +++ b/src/main/java/cz/jzitnik/game/mobs/HittableMobDrops.java @@ -5,6 +5,7 @@ import cz.jzitnik.annotations.injectors.InjectState; import cz.jzitnik.events.DroppedItemRerender; import cz.jzitnik.events.InventoryRerender; import cz.jzitnik.game.GameRoom; +import cz.jzitnik.game.GameRoomPart; import cz.jzitnik.game.GameState; import cz.jzitnik.game.Player; import cz.jzitnik.game.items.GameItem; @@ -29,13 +30,13 @@ public abstract class HittableMobDrops extends HittableMob { private final Supplier itemDropSupplier; - public HittableMobDrops(BufferedImage texture, RoomTask task, RoomCords cords, int initialHealth, Supplier itemDropSupplier) { - super(texture, task, cords, initialHealth); + public HittableMobDrops(BufferedImage texture, RoomTask task, RoomCords cords, GameRoomPart collider, int initialHealth, Supplier itemDropSupplier) { + super(texture, task, cords, collider, initialHealth); this.itemDropSupplier = itemDropSupplier; } - public HittableMobDrops(Supplier itemDropSupplier, BufferedImage texture, RoomTask task, RoomCords cords, int initialHealth) { - super(texture, task, cords, initialHealth); + public HittableMobDrops(Supplier itemDropSupplier, BufferedImage texture, RoomTask task, RoomCords cords, GameRoomPart collider, int initialHealth) { + super(texture, task, cords, collider, initialHealth); this.itemDropSupplier = () -> new GameItem[]{ itemDropSupplier.get() }; diff --git a/src/main/java/cz/jzitnik/game/mobs/HittableMobNoDrops.java b/src/main/java/cz/jzitnik/game/mobs/HittableMobNoDrops.java index 5a7cb06..7e103b7 100644 --- a/src/main/java/cz/jzitnik/game/mobs/HittableMobNoDrops.java +++ b/src/main/java/cz/jzitnik/game/mobs/HittableMobNoDrops.java @@ -1,13 +1,14 @@ package cz.jzitnik.game.mobs; +import cz.jzitnik.game.GameRoomPart; import cz.jzitnik.game.utils.RoomCords; import cz.jzitnik.utils.roomtasks.RoomTask; import java.awt.image.BufferedImage; public abstract class HittableMobNoDrops extends HittableMob { - public HittableMobNoDrops(BufferedImage texture, RoomTask task, RoomCords cords, int initialHealth) { - super(texture, task, cords, initialHealth); + public HittableMobNoDrops(BufferedImage texture, RoomTask task, RoomCords cords, GameRoomPart collider, int initialHealth) { + super(texture, task, cords, collider, initialHealth); } @Override diff --git a/src/main/java/cz/jzitnik/game/mobs/Mob.java b/src/main/java/cz/jzitnik/game/mobs/Mob.java index 3fa7e6a..819cc1a 100644 --- a/src/main/java/cz/jzitnik/game/mobs/Mob.java +++ b/src/main/java/cz/jzitnik/game/mobs/Mob.java @@ -1,6 +1,7 @@ package cz.jzitnik.game.mobs; import cz.jzitnik.annotations.injectors.InjectDependency; +import cz.jzitnik.game.GameRoomPart; import cz.jzitnik.game.utils.Renderable; import cz.jzitnik.game.utils.RoomCords; import cz.jzitnik.game.utils.Selectable; @@ -17,6 +18,7 @@ public abstract class Mob implements Renderable, Selectable { protected RoomTask[] tasks; protected final RoomCords cords; + protected final GameRoomPart collider; @InjectDependency private RoomTaskScheduler roomTaskScheduler; @@ -28,16 +30,18 @@ public abstract class Mob implements Renderable, Selectable { roomTaskScheduler.registerNewMob(this, oldTasks); } - public Mob(BufferedImage texture, RoomTask task, RoomCords cords) { + public Mob(BufferedImage texture, RoomTask task, RoomCords cords, GameRoomPart collider) { this.texture = texture; this.tasks = new RoomTask[] {task}; this.cords = cords; + this.collider = collider; } - public Mob(BufferedImage texture, RoomTask[] tasks, RoomCords cords) { + public Mob(BufferedImage texture, RoomTask[] tasks, RoomCords cords, GameRoomPart collider) { this.texture = texture; this.tasks = tasks; this.cords = cords; + this.collider = collider; } @Setter diff --git a/src/main/java/cz/jzitnik/game/mobs/tasks/MobFollowingPlayerTask.java b/src/main/java/cz/jzitnik/game/mobs/tasks/MobFollowingPlayerTask.java index b138880..45a053b 100644 --- a/src/main/java/cz/jzitnik/game/mobs/tasks/MobFollowingPlayerTask.java +++ b/src/main/java/cz/jzitnik/game/mobs/tasks/MobFollowingPlayerTask.java @@ -59,7 +59,7 @@ public class MobFollowingPlayerTask extends RoomTask { protected static void moveMob(RoomCords playerCords, Mob mob, GameState gameState, int speed, ResourceManager resourceManager, TerminalState terminalState, ScreenBuffer screenBuffer, Debugging debugging, EventManager eventManager) { RoomCords mobCords = mob.getCords(); List solidParts = gameState.getCurrentRoom().getColliders(); - List path = AStarAlg.findPath(mobCords, playerCords, solidParts); + List path = AStarAlg.findPath(mobCords, playerCords, solidParts, mob.getCollider()); if (path.size() > 1) { int targetIndex = Math.min(speed, path.size() - 1); diff --git a/src/main/java/cz/jzitnik/game/mobs/tasks/utils/AStarAlg.java b/src/main/java/cz/jzitnik/game/mobs/tasks/utils/AStarAlg.java index f3f9a4a..d1181e4 100644 --- a/src/main/java/cz/jzitnik/game/mobs/tasks/utils/AStarAlg.java +++ b/src/main/java/cz/jzitnik/game/mobs/tasks/utils/AStarAlg.java @@ -12,7 +12,7 @@ public class AStarAlg { private static final int MIN_Y = 10; private static final int MAX_Y = 113; - public static List findPath(RoomCords start, RoomCords target, List colliders) { + public static List findPath(RoomCords start, RoomCords target, List colliders, GameRoomPart mobCollider) { PriorityQueue openSet = new PriorityQueue<>(Comparator.comparingInt(n -> n.f)); Set closedSet = new HashSet<>(); @@ -34,7 +34,7 @@ public class AStarAlg { String neighborKey = neighbor.x + "," + neighbor.y; if (closedSet.contains(neighborKey)) continue; - if (!isValidPosition(neighbor.x, neighbor.y, colliders)) { + if (!isValidPosition(neighbor.x, neighbor.y, colliders, mobCollider)) { if (neighbor.x != target.getX() || neighbor.y != target.getY()) { continue; } @@ -68,14 +68,17 @@ public class AStarAlg { return neighbors; } - private static boolean isValidPosition(int x, int y, List colliders) { + private static boolean isValidPosition(int x, int y, List colliders, GameRoomPart mobCollider) { if (x < MIN_X || x > MAX_X) return false; if (y < MIN_Y || y > MAX_Y) return false; - RoomCords temp = new RoomCords(x, y); + var temp = new GameRoomPart( + new RoomCords(mobCollider.getStart().getX() + x, mobCollider.getStart().getY() + y), + new RoomCords(mobCollider.getEnd().getX() + x, mobCollider.getEnd().getY() + y) + ); for (GameRoomPart part : colliders) { - if (part.isWithin(temp)) { + if (part.isOverlapping(temp)) { return false; } } diff --git a/src/main/java/cz/jzitnik/game/setup/GameSetup.java b/src/main/java/cz/jzitnik/game/setup/GameSetup.java index a3ff9d9..31a2497 100644 --- a/src/main/java/cz/jzitnik/game/setup/GameSetup.java +++ b/src/main/java/cz/jzitnik/game/setup/GameSetup.java @@ -35,6 +35,12 @@ public class GameSetup { gameState.setCurrentRoom(mainRoom); - gameState.setPlayer(new Player(new RoomCords(90, 100))); + gameState.setPlayer(new Player( + new RoomCords(90, 100), + new GameRoomPart( + new RoomCords(0, 52), + new RoomCords(44, 78) + ) + )); } } diff --git a/src/main/java/cz/jzitnik/game/setup/enemies/Pepa.java b/src/main/java/cz/jzitnik/game/setup/enemies/Pepa.java index 483f4a0..fc12ebe 100644 --- a/src/main/java/cz/jzitnik/game/setup/enemies/Pepa.java +++ b/src/main/java/cz/jzitnik/game/setup/enemies/Pepa.java @@ -1,5 +1,6 @@ package cz.jzitnik.game.setup.enemies; +import cz.jzitnik.game.GameRoomPart; import cz.jzitnik.game.ResourceManager; import cz.jzitnik.game.dialog.Dialog; import cz.jzitnik.game.dialog.OnEnd; @@ -11,7 +12,12 @@ import cz.jzitnik.utils.roomtasks.RoomTask; public class Pepa extends DialogMob { public Pepa(ResourceManager resourceManager, RoomCords cords) { - super(resourceManager.getResource(ResourceManager.Resource.PLAYER_FRONT), new RoomTask[]{}, cords, null + super(resourceManager.getResource(ResourceManager.Resource.PLAYER_FRONT), new RoomTask[]{}, cords, + new GameRoomPart( + new RoomCords(0, 52), + new RoomCords(44, 78) + ), + null ); dialog = new Dialog( diff --git a/src/main/java/cz/jzitnik/game/setup/enemies/Zombie.java b/src/main/java/cz/jzitnik/game/setup/enemies/Zombie.java index d55c14f..df931fd 100644 --- a/src/main/java/cz/jzitnik/game/setup/enemies/Zombie.java +++ b/src/main/java/cz/jzitnik/game/setup/enemies/Zombie.java @@ -1,5 +1,6 @@ package cz.jzitnik.game.setup.enemies; +import cz.jzitnik.game.GameRoomPart; import cz.jzitnik.game.ResourceManager; import cz.jzitnik.game.mobs.HittableMobDrops; import cz.jzitnik.game.mobs.tasks.EnemyPlayerHittingTask; @@ -12,7 +13,13 @@ import lombok.extern.slf4j.Slf4j; @Slf4j public class Zombie extends HittableMobDrops { public Zombie(ResourceManager resourceManager, RoomCords cords) { - super(() -> new Apple(resourceManager), resourceManager.getResource(ResourceManager.Resource.PLAYER_FRONT), null, cords, 10); + super(() -> new Apple(resourceManager), resourceManager.getResource(ResourceManager.Resource.PLAYER_FRONT), null, cords, + new GameRoomPart( + new RoomCords(0, 52), + new RoomCords(44, 78) + ), + 10 + ); tasks = new RoomTask[]{ new MobFollowingPlayerTask(this, 1, 100), new EnemyPlayerHittingTask(this, 500, 15, () -> 5) diff --git a/src/main/java/cz/jzitnik/game/setup/rooms/MainRoom.java b/src/main/java/cz/jzitnik/game/setup/rooms/MainRoom.java index 1b2cbc9..14dff11 100644 --- a/src/main/java/cz/jzitnik/game/setup/rooms/MainRoom.java +++ b/src/main/java/cz/jzitnik/game/setup/rooms/MainRoom.java @@ -22,8 +22,8 @@ public class MainRoom extends GameRoom { new Apple(resourceManager) }); addCollider(new GameRoomPart( - new RoomCords(60, 10), - new RoomCords(135, 15) + new RoomCords(100, 45), + new RoomCords(140, 67) )); addObject(chest); diff --git a/src/main/java/cz/jzitnik/game/utils/RoomCords.java b/src/main/java/cz/jzitnik/game/utils/RoomCords.java index 20d0fe4..8b0ba44 100644 --- a/src/main/java/cz/jzitnik/game/utils/RoomCords.java +++ b/src/main/java/cz/jzitnik/game/utils/RoomCords.java @@ -23,8 +23,13 @@ public class RoomCords implements Cloneable { this.y = y; } - public void updateCordsWithColliders(List colliders, int x, int y) { - if (colliders.stream().anyMatch(collider -> collider.isWithin(new RoomCords(x, y)))) { + public void updateCordsWithColliders(List colliders, int x, int y, GameRoomPart playerCollider) { + var normalizedPlayerCollider = new GameRoomPart( + new RoomCords(playerCollider.getStart().getX() + x, playerCollider.getStart().getY() + y), + new RoomCords(playerCollider.getEnd().getX() + x, playerCollider.getEnd().getY() + y) + ); + + if (colliders.stream().anyMatch(collider -> collider.isOverlapping(normalizedPlayerCollider))) { return; } updateCords(x, y); diff --git a/src/main/java/cz/jzitnik/utils/RerenderUtils.java b/src/main/java/cz/jzitnik/utils/RerenderUtils.java index 43abb6f..942dc45 100644 --- a/src/main/java/cz/jzitnik/utils/RerenderUtils.java +++ b/src/main/java/cz/jzitnik/utils/RerenderUtils.java @@ -73,9 +73,9 @@ public class RerenderUtils { if (x >= player.getPlayerCords().getX() && x < player.getPlayerCords().getX() + playerTexture.getWidth() - 1 && y >= player.getPlayerCords().getY() && y <= player.getPlayerCords().getY() + playerTexture.getHeight() - 1) { int relativeX = x - player.getPlayerCords().getX(); int relativeY = y - player.getPlayerCords().getY(); + var playerCollider = player.getCollider(); - - if (debugging.isRenderPlayerCollider() && relativeX == 0 && relativeY == 0) { + if (debugging.isRenderPlayerCollider() && playerCollider.isWithin(new RoomCords(relativeX, relativeY))) { return new PixelResult(0xFFFF0000, false); }