feat: Collisions

This commit is contained in:
2025-12-21 15:07:34 +01:00
parent fdb6c3075d
commit d5f8eb9ed8
10 changed files with 110 additions and 21 deletions

View File

@@ -0,0 +1,11 @@
package cz.jzitnik.config;
import cz.jzitnik.annotations.Config;
import lombok.Getter;
@Getter
@Config
public class Debugging {
private final boolean renderColliders = false;
private final boolean renderPlayerCollider = false;
}

View File

@@ -5,8 +5,10 @@ import com.googlecode.lanterna.TerminalSize;
import com.googlecode.lanterna.TextColor; import com.googlecode.lanterna.TextColor;
import com.googlecode.lanterna.screen.TerminalScreen; import com.googlecode.lanterna.screen.TerminalScreen;
import cz.jzitnik.annotations.EventHandler; import cz.jzitnik.annotations.EventHandler;
import cz.jzitnik.annotations.injectors.InjectConfig;
import cz.jzitnik.annotations.injectors.InjectDependency; import cz.jzitnik.annotations.injectors.InjectDependency;
import cz.jzitnik.annotations.injectors.InjectState; import cz.jzitnik.annotations.injectors.InjectState;
import cz.jzitnik.config.Debugging;
import cz.jzitnik.events.FullRoomDraw; import cz.jzitnik.events.FullRoomDraw;
import cz.jzitnik.events.RerenderScreen; import cz.jzitnik.events.RerenderScreen;
import cz.jzitnik.events.TerminalTooSmallEvent; import cz.jzitnik.events.TerminalTooSmallEvent;
@@ -54,6 +56,9 @@ public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
@InjectState @InjectState
private RenderState renderState; private RenderState renderState;
@InjectConfig
private Debugging debugging;
public enum DoorPosition { public enum DoorPosition {
TOP, TOP,
LEFT, LEFT,
@@ -89,7 +94,7 @@ public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
RerenderUtils.PixelResult pixelResult = RerenderUtils.getPixel(currentRoom, room, doors, doorPositions, player, playerTexture, x, y); RerenderUtils.PixelResult pixelResult = RerenderUtils.getPixel(currentRoom, room, doors, doorPositions, player, playerTexture, x, y, debugging);
int pixel = pixelResult.pixel(); int pixel = pixelResult.pixel();
int red = (pixel >> 16) & 0xff; int red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff; int green = (pixel >> 8) & 0xff;

View File

@@ -2,8 +2,10 @@ package cz.jzitnik.events.handlers;
import com.googlecode.lanterna.TerminalPosition; import com.googlecode.lanterna.TerminalPosition;
import cz.jzitnik.annotations.EventHandler; import cz.jzitnik.annotations.EventHandler;
import cz.jzitnik.annotations.injectors.InjectConfig;
import cz.jzitnik.annotations.injectors.InjectDependency; import cz.jzitnik.annotations.injectors.InjectDependency;
import cz.jzitnik.annotations.injectors.InjectState; import cz.jzitnik.annotations.injectors.InjectState;
import cz.jzitnik.config.Debugging;
import cz.jzitnik.events.MouseAction; import cz.jzitnik.events.MouseAction;
import cz.jzitnik.events.MouseMoveEvent; import cz.jzitnik.events.MouseMoveEvent;
import cz.jzitnik.events.RerenderScreen; import cz.jzitnik.events.RerenderScreen;
@@ -50,6 +52,9 @@ public class MouseMoveEventHandler extends AbstractEventHandler<MouseMoveEvent>
@InjectDependency @InjectDependency
private EventManager eventManager; private EventManager eventManager;
@InjectConfig
private Debugging debugging;
@Override @Override
public void handle(MouseMoveEvent event) { public void handle(MouseMoveEvent event) {
MouseAction mouseAction = event.getMouseAction(); MouseAction mouseAction = event.getMouseAction();
@@ -110,7 +115,8 @@ public class MouseMoveEventHandler extends AbstractEventHandler<MouseMoveEvent>
player, player,
playerTexture, playerTexture,
screenBuffer, screenBuffer,
resourceManager resourceManager,
debugging
); );
parts.add(new RerenderScreen.ScreenPart( parts.add(new RerenderScreen.ScreenPart(

View File

@@ -3,8 +3,10 @@ package cz.jzitnik.events.handlers;
import com.googlecode.lanterna.TerminalPosition; import com.googlecode.lanterna.TerminalPosition;
import com.googlecode.lanterna.input.KeyStroke; import com.googlecode.lanterna.input.KeyStroke;
import cz.jzitnik.annotations.EventHandler; import cz.jzitnik.annotations.EventHandler;
import cz.jzitnik.annotations.injectors.InjectConfig;
import cz.jzitnik.annotations.injectors.InjectDependency; import cz.jzitnik.annotations.injectors.InjectDependency;
import cz.jzitnik.annotations.injectors.InjectState; import cz.jzitnik.annotations.injectors.InjectState;
import cz.jzitnik.config.Debugging;
import cz.jzitnik.events.PlayerMoveEvent; import cz.jzitnik.events.PlayerMoveEvent;
import cz.jzitnik.events.RerenderScreen; import cz.jzitnik.events.RerenderScreen;
import cz.jzitnik.events.RoomChangeEvent; import cz.jzitnik.events.RoomChangeEvent;
@@ -45,11 +47,15 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
@InjectDependency @InjectDependency
private ResourceManager resourceManager; private ResourceManager resourceManager;
@InjectConfig
private Debugging debugging;
@Override @Override
public void handle(PlayerMoveEvent event) { public void handle(PlayerMoveEvent event) {
KeyStroke keyStroke = event.getKeyStroke(); KeyStroke keyStroke = event.getKeyStroke();
Player player = gameState.getPlayer(); Player player = gameState.getPlayer();
RoomCords playerCords = player.getPlayerCords(); RoomCords playerCords = player.getPlayerCords();
GameRoom currentRoom = gameState.getCurrentRoom();
int moveStep = 3; int moveStep = 3;
@@ -63,7 +69,7 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
} }
return; return;
} }
playerCords.updateCords(player.getPlayerCords().getX(), playerCords.getY() - moveStep); playerCords.updateCordsWithColliders(currentRoom.getColliders(), player.getPlayerCords().getX(), playerCords.getY() - moveStep);
} }
case 'a' -> { case 'a' -> {
if (originalPlayerX <= 30) { if (originalPlayerX <= 30) {
@@ -72,7 +78,7 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
} }
return; return;
} }
playerCords.updateCords(player.getPlayerCords().getX() - moveStep, playerCords.getY()); playerCords.updateCordsWithColliders(currentRoom.getColliders(), player.getPlayerCords().getX() - moveStep, playerCords.getY());
} }
case 's' -> { case 's' -> {
if (originalPlayerY >= 110) { if (originalPlayerY >= 110) {
@@ -81,7 +87,7 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
} }
return; return;
} }
playerCords.updateCords(player.getPlayerCords().getX(), playerCords.getY() + moveStep); playerCords.updateCordsWithColliders(currentRoom.getColliders(), player.getPlayerCords().getX(), playerCords.getY() + moveStep);
} }
case 'd' -> { case 'd' -> {
if (originalPlayerX >= 155) { if (originalPlayerX >= 155) {
@@ -90,7 +96,7 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
} }
return; return;
} }
playerCords.updateCords(player.getPlayerCords().getX() + moveStep, playerCords.getY()); playerCords.updateCordsWithColliders(currentRoom.getColliders(), player.getPlayerCords().getX() + moveStep, playerCords.getY());
} }
} }
int newPlayerX = playerCords.getX(); int newPlayerX = playerCords.getX();
@@ -102,13 +108,12 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
int forEndX = Math.max(originalPlayerX, newPlayerX) + playerTexture.getWidth(); int forEndX = Math.max(originalPlayerX, newPlayerX) + playerTexture.getWidth();
int forEndY = Math.max(originalPlayerY, newPlayerY) + playerTexture.getHeight(); int forEndY = Math.max(originalPlayerY, newPlayerY) + playerTexture.getHeight();
GameRoom currentRoom = gameState.getCurrentRoom();
BufferedImage room = resourceManager.getResource(currentRoom.getTexture()); BufferedImage room = resourceManager.getResource(currentRoom.getTexture());
var start = RerenderUtils.getStart(room, terminalState.getTerminalScreen().getTerminalSize()); var start = RerenderUtils.getStart(room, terminalState.getTerminalScreen().getTerminalSize());
int startX = start.getX(); int startX = start.getX();
int startY = start.getY(); int startY = start.getY();
RerenderUtils.rerenderPart(forStartX, forEndX, forStartY, forEndY, startX, startY, currentRoom, room, player, playerTexture, screenBuffer, resourceManager); RerenderUtils.rerenderPart(forStartX, forEndX, forStartY, forEndY, startX, startY, currentRoom, room, player, playerTexture, screenBuffer, resourceManager, debugging);
eventManager.emitEvent(new RerenderScreen( eventManager.emitEvent(new RerenderScreen(
new RerenderScreen.ScreenPart( new RerenderScreen.ScreenPart(

View File

@@ -16,6 +16,8 @@ public class GameRoom {
private GameRoom down; private GameRoom down;
private final Pixel[][] overrideBuffer; private final Pixel[][] overrideBuffer;
private final ResourceManager.Resource texture; private final ResourceManager.Resource texture;
private final List<GameObject> objects = new ArrayList<>();
private final List<GameRoomPart> colliders = new ArrayList<>();
public GameRoom(ResourceManager.Resource texture) { public GameRoom(ResourceManager.Resource texture) {
this.texture = texture; this.texture = texture;
@@ -35,12 +37,14 @@ public class GameRoom {
this.overrideBuffer = overrideBuffer; this.overrideBuffer = overrideBuffer;
} }
private final List<GameObject> objects = new ArrayList<>();
public void addObject(GameObject gameObject) { public void addObject(GameObject gameObject) {
objects.addFirst(gameObject); objects.addFirst(gameObject);
} }
public void addCollider(GameRoomPart collider) {
colliders.add(collider);
}
public void setLeft(GameRoom left) { public void setLeft(GameRoom left) {
setLeft(left, true); setLeft(left, true);
} }

View File

@@ -0,0 +1,22 @@
package cz.jzitnik.game;
import cz.jzitnik.game.utils.RoomCords;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;
@Data
@AllArgsConstructor
@ToString
public class GameRoomPart {
private RoomCords start;
private RoomCords end;
public boolean isWithin(RoomCords cords) {
return
cords.getX() >= start.getX() &&
cords.getX() <= end.getX() &&
cords.getY() >= start.getY() &&
cords.getY() <= end.getY();
}
}

View File

@@ -3,8 +3,10 @@ package cz.jzitnik.game.objects;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.googlecode.lanterna.TerminalPosition; import com.googlecode.lanterna.TerminalPosition;
import com.googlecode.lanterna.TextColor; import com.googlecode.lanterna.TextColor;
import cz.jzitnik.annotations.injectors.InjectConfig;
import cz.jzitnik.annotations.injectors.InjectDependency; import cz.jzitnik.annotations.injectors.InjectDependency;
import cz.jzitnik.annotations.injectors.InjectState; import cz.jzitnik.annotations.injectors.InjectState;
import cz.jzitnik.config.Debugging;
import cz.jzitnik.events.MouseAction; import cz.jzitnik.events.MouseAction;
import cz.jzitnik.events.RerenderScreen; import cz.jzitnik.events.RerenderScreen;
import cz.jzitnik.game.GameRoom; import cz.jzitnik.game.GameRoom;
@@ -60,6 +62,9 @@ public final class Chest extends GameObject implements Interactable, UIClickHand
@InjectState @InjectState
private TerminalState terminalState; private TerminalState terminalState;
@InjectConfig
private Debugging debugging;
public Chest(DependencyManager dm, ResourceManager resourceManager, RoomCords cords, GameItem[] items) { public Chest(DependencyManager dm, ResourceManager resourceManager, RoomCords cords, GameItem[] items) {
super(resourceManager.getResource(ResourceManager.Resource.CHEST), cords, true); super(resourceManager.getResource(ResourceManager.Resource.CHEST), cords, true);
this.items = Lists.newArrayList(items); this.items = Lists.newArrayList(items);
@@ -145,7 +150,8 @@ public final class Chest extends GameObject implements Interactable, UIClickHand
player, player,
playerTexture, playerTexture,
screenBuffer, screenBuffer,
resourceManager resourceManager,
debugging
); );
RerenderScreen.ScreenPart sp = new RerenderScreen.ScreenPart(guiStart, guiEnd); RerenderScreen.ScreenPart sp = new RerenderScreen.ScreenPart(guiStart, guiEnd);
@@ -188,7 +194,8 @@ public final class Chest extends GameObject implements Interactable, UIClickHand
player, player,
playerTexture, playerTexture,
x, x,
y y,
debugging
).pixel(); ).pixel();
buffer[y + start.getY()][x + start.getX()] = pixelToColored(pixel); buffer[y + start.getY()][x + start.getX()] = pixelToColored(pixel);

View File

@@ -3,10 +3,7 @@ package cz.jzitnik.game.setup;
import cz.jzitnik.annotations.Dependency; import cz.jzitnik.annotations.Dependency;
import cz.jzitnik.annotations.injectors.InjectDependency; import cz.jzitnik.annotations.injectors.InjectDependency;
import cz.jzitnik.annotations.injectors.InjectState; import cz.jzitnik.annotations.injectors.InjectState;
import cz.jzitnik.game.GameRoom; import cz.jzitnik.game.*;
import cz.jzitnik.game.GameState;
import cz.jzitnik.game.Player;
import cz.jzitnik.game.ResourceManager;
import cz.jzitnik.game.items.GameItem; import cz.jzitnik.game.items.GameItem;
import cz.jzitnik.game.items.WoodenSword; import cz.jzitnik.game.items.WoodenSword;
import cz.jzitnik.game.objects.Chest; import cz.jzitnik.game.objects.Chest;
@@ -25,7 +22,7 @@ public class GameSetup {
private DependencyManager dependencyManager; private DependencyManager dependencyManager;
public void setup() { public void setup() {
gameState.setScreen(new IntroScene(dependencyManager)); //gameState.setScreen(new IntroScene(dependencyManager));
GameRoom mainRoom = new GameRoom(ResourceManager.Resource.ROOM1); GameRoom mainRoom = new GameRoom(ResourceManager.Resource.ROOM1);
GameRoom rightRoom = new GameRoom(ResourceManager.Resource.ROOM2); GameRoom rightRoom = new GameRoom(ResourceManager.Resource.ROOM2);
@@ -44,6 +41,10 @@ public class GameSetup {
new WoodenSword(resourceManager), new WoodenSword(resourceManager),
}); });
mainRoom.addObject(chest); mainRoom.addObject(chest);
mainRoom.addCollider(new GameRoomPart(
new RoomCords(60, 10),
new RoomCords(135, 15)
));
gameState.setCurrentRoom(mainRoom); gameState.setCurrentRoom(mainRoom);

View File

@@ -1,8 +1,13 @@
package cz.jzitnik.game.utils; package cz.jzitnik.game.utils;
import cz.jzitnik.game.GameRoomPart;
import lombok.Getter; import lombok.Getter;
import lombok.ToString; import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
@Slf4j
@ToString @ToString
@Getter @Getter
public class RoomCords { public class RoomCords {
@@ -17,4 +22,14 @@ public class RoomCords {
this.x = x; this.x = x;
this.y = y; this.y = y;
} }
public void updateCordsWithColliders(List<GameRoomPart> colliders, int x, int y) {
log.debug("Collider: {}", colliders.get(0));
log.debug("x: {}, y: {}", x, y);
if (colliders.stream().anyMatch(collider -> collider.isWithin(new RoomCords(x, y)))) {
return;
}
updateCords(x, y);
}
} }

View File

@@ -2,6 +2,7 @@ package cz.jzitnik.utils;
import com.googlecode.lanterna.TerminalSize; import com.googlecode.lanterna.TerminalSize;
import com.googlecode.lanterna.TextColor; import com.googlecode.lanterna.TextColor;
import cz.jzitnik.config.Debugging;
import cz.jzitnik.events.handlers.FullRoomDrawHandler; import cz.jzitnik.events.handlers.FullRoomDrawHandler;
import cz.jzitnik.game.GameRoom; import cz.jzitnik.game.GameRoom;
import cz.jzitnik.game.Player; import cz.jzitnik.game.Player;
@@ -31,14 +32,14 @@ public class RerenderUtils {
return new RoomCords(x, y); return new RoomCords(x, y);
} }
public static void rerenderPart(int startX, int endX, int startY, int endY, int screenStartX, int screenStartY, GameRoom currentRoom, BufferedImage room, Player player, BufferedImage playerTexture, ScreenBuffer screenBuffer, ResourceManager resourceManager) { public static void rerenderPart(int startX, int endX, int startY, int endY, int screenStartX, int screenStartY, GameRoom currentRoom, BufferedImage room, Player player, BufferedImage playerTexture, ScreenBuffer screenBuffer, ResourceManager resourceManager, Debugging debugging) {
var buffer = screenBuffer.getRenderedBuffer(); var buffer = screenBuffer.getRenderedBuffer();
var overrideBuffer = currentRoom.getOverrideBuffer(); var overrideBuffer = currentRoom.getOverrideBuffer();
BufferedImage doors = resourceManager.getResource(ResourceManager.Resource.DOORS); BufferedImage doors = resourceManager.getResource(ResourceManager.Resource.DOORS);
Set<FullRoomDrawHandler.DoorPosition> doorPositions = RerenderUtils.getDoorPositions(currentRoom); Set<FullRoomDrawHandler.DoorPosition> doorPositions = RerenderUtils.getDoorPositions(currentRoom);
for (int x = startX; x <= endX; x++) { for (int x = startX; x <= endX; x++) {
for (int y = startY; y <= endY; y++) { for (int y = startY; y <= endY; y++) {
PixelResult pixelResult = getPixel(currentRoom, room, doors, doorPositions, player, playerTexture, x, y); PixelResult pixelResult = getPixel(currentRoom, room, doors, doorPositions, player, playerTexture, x, y, debugging);
int pixel = pixelResult.pixel(); int pixel = pixelResult.pixel();
int red = (pixel >> 16) & 0xff; int red = (pixel >> 16) & 0xff;
@@ -57,9 +58,21 @@ public class RerenderUtils {
public record PixelResult(int pixel, boolean isPlayer) {} public record PixelResult(int pixel, boolean isPlayer) {}
public static PixelResult getPixel(GameRoom currentRoom, BufferedImage room, BufferedImage doors, Set<FullRoomDrawHandler.DoorPosition> doorPositions, Player player, BufferedImage playerTexture, int x, int y) { public static PixelResult getPixel(GameRoom currentRoom, BufferedImage room, BufferedImage doors, Set<FullRoomDrawHandler.DoorPosition> doorPositions, Player player, BufferedImage playerTexture, int x, int y, Debugging debugging) {
if (debugging.isRenderColliders() && currentRoom.getColliders().stream().anyMatch(collider -> collider.isWithin(new RoomCords(x, y)))) {
return new PixelResult(0xFFFF0000, false);
}
if (x >= player.getPlayerCords().getX() && x < player.getPlayerCords().getX() + playerTexture.getWidth() - 1 && y >= player.getPlayerCords().getY() && y <= player.getPlayerCords().getY() + playerTexture.getHeight() - 1) { if (x >= player.getPlayerCords().getX() && x < player.getPlayerCords().getX() + playerTexture.getWidth() - 1 && y >= player.getPlayerCords().getY() && y <= player.getPlayerCords().getY() + playerTexture.getHeight() - 1) {
int pixel = playerTexture.getRGB(x - player.getPlayerCords().getX(), y - player.getPlayerCords().getY()); int relativeX = x - player.getPlayerCords().getX();
int relativeY = y - player.getPlayerCords().getY();
if (debugging.isRenderPlayerCollider() && relativeX == 0 && relativeY == 0){
return new PixelResult(0xFFFF0000, false);
}
int pixel = playerTexture.getRGB(relativeX, relativeY);
int alpha = (pixel >> 24) & 0xff; int alpha = (pixel >> 24) & 0xff;
if (alpha != 0) { if (alpha != 0) {