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.screen.TerminalScreen;
import cz.jzitnik.annotations.EventHandler;
import cz.jzitnik.annotations.injectors.InjectConfig;
import cz.jzitnik.annotations.injectors.InjectDependency;
import cz.jzitnik.annotations.injectors.InjectState;
import cz.jzitnik.config.Debugging;
import cz.jzitnik.events.FullRoomDraw;
import cz.jzitnik.events.RerenderScreen;
import cz.jzitnik.events.TerminalTooSmallEvent;
@@ -54,6 +56,9 @@ public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
@InjectState
private RenderState renderState;
@InjectConfig
private Debugging debugging;
public enum DoorPosition {
TOP,
LEFT,
@@ -89,7 +94,7 @@ public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
for (int y = 0; y < height; y++) {
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 red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff;

View File

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

View File

@@ -16,6 +16,8 @@ public class GameRoom {
private GameRoom down;
private final Pixel[][] overrideBuffer;
private final ResourceManager.Resource texture;
private final List<GameObject> objects = new ArrayList<>();
private final List<GameRoomPart> colliders = new ArrayList<>();
public GameRoom(ResourceManager.Resource texture) {
this.texture = texture;
@@ -35,12 +37,14 @@ public class GameRoom {
this.overrideBuffer = overrideBuffer;
}
private final List<GameObject> objects = new ArrayList<>();
public void addObject(GameObject gameObject) {
objects.addFirst(gameObject);
}
public void addCollider(GameRoomPart collider) {
colliders.add(collider);
}
public void setLeft(GameRoom left) {
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.googlecode.lanterna.TerminalPosition;
import com.googlecode.lanterna.TextColor;
import cz.jzitnik.annotations.injectors.InjectConfig;
import cz.jzitnik.annotations.injectors.InjectDependency;
import cz.jzitnik.annotations.injectors.InjectState;
import cz.jzitnik.config.Debugging;
import cz.jzitnik.events.MouseAction;
import cz.jzitnik.events.RerenderScreen;
import cz.jzitnik.game.GameRoom;
@@ -60,6 +62,9 @@ public final class Chest extends GameObject implements Interactable, UIClickHand
@InjectState
private TerminalState terminalState;
@InjectConfig
private Debugging debugging;
public Chest(DependencyManager dm, ResourceManager resourceManager, RoomCords cords, GameItem[] items) {
super(resourceManager.getResource(ResourceManager.Resource.CHEST), cords, true);
this.items = Lists.newArrayList(items);
@@ -145,7 +150,8 @@ public final class Chest extends GameObject implements Interactable, UIClickHand
player,
playerTexture,
screenBuffer,
resourceManager
resourceManager,
debugging
);
RerenderScreen.ScreenPart sp = new RerenderScreen.ScreenPart(guiStart, guiEnd);
@@ -188,7 +194,8 @@ public final class Chest extends GameObject implements Interactable, UIClickHand
player,
playerTexture,
x,
y
y,
debugging
).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.injectors.InjectDependency;
import cz.jzitnik.annotations.injectors.InjectState;
import cz.jzitnik.game.GameRoom;
import cz.jzitnik.game.GameState;
import cz.jzitnik.game.Player;
import cz.jzitnik.game.ResourceManager;
import cz.jzitnik.game.*;
import cz.jzitnik.game.items.GameItem;
import cz.jzitnik.game.items.WoodenSword;
import cz.jzitnik.game.objects.Chest;
@@ -25,7 +22,7 @@ public class GameSetup {
private DependencyManager dependencyManager;
public void setup() {
gameState.setScreen(new IntroScene(dependencyManager));
//gameState.setScreen(new IntroScene(dependencyManager));
GameRoom mainRoom = new GameRoom(ResourceManager.Resource.ROOM1);
GameRoom rightRoom = new GameRoom(ResourceManager.Resource.ROOM2);
@@ -44,6 +41,10 @@ public class GameSetup {
new WoodenSword(resourceManager),
});
mainRoom.addObject(chest);
mainRoom.addCollider(new GameRoomPart(
new RoomCords(60, 10),
new RoomCords(135, 15)
));
gameState.setCurrentRoom(mainRoom);

View File

@@ -1,8 +1,13 @@
package cz.jzitnik.game.utils;
import cz.jzitnik.game.GameRoomPart;
import lombok.Getter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
@Slf4j
@ToString
@Getter
public class RoomCords {
@@ -17,4 +22,14 @@ public class RoomCords {
this.x = x;
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.TextColor;
import cz.jzitnik.config.Debugging;
import cz.jzitnik.events.handlers.FullRoomDrawHandler;
import cz.jzitnik.game.GameRoom;
import cz.jzitnik.game.Player;
@@ -31,14 +32,14 @@ public class RerenderUtils {
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 overrideBuffer = currentRoom.getOverrideBuffer();
BufferedImage doors = resourceManager.getResource(ResourceManager.Resource.DOORS);
Set<FullRoomDrawHandler.DoorPosition> doorPositions = RerenderUtils.getDoorPositions(currentRoom);
for (int x = startX; x <= endX; x++) {
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 red = (pixel >> 16) & 0xff;
@@ -57,9 +58,21 @@ public class RerenderUtils {
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) {
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;
if (alpha != 0) {