diff --git a/src/main/java/cz/jzitnik/events/MouseMoveEvent.java b/src/main/java/cz/jzitnik/events/MouseMoveEvent.java new file mode 100644 index 0000000..9bb769b --- /dev/null +++ b/src/main/java/cz/jzitnik/events/MouseMoveEvent.java @@ -0,0 +1,11 @@ +package cz.jzitnik.events; + +import cz.jzitnik.utils.events.Event; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class MouseMoveEvent implements Event { + private MouseAction mouseAction; +} diff --git a/src/main/java/cz/jzitnik/events/handlers/FullRoomDrawHandler.java b/src/main/java/cz/jzitnik/events/handlers/FullRoomDrawHandler.java index 99a8829..181cd55 100644 --- a/src/main/java/cz/jzitnik/events/handlers/FullRoomDrawHandler.java +++ b/src/main/java/cz/jzitnik/events/handlers/FullRoomDrawHandler.java @@ -13,13 +13,13 @@ import cz.jzitnik.game.GameRoom; import cz.jzitnik.game.GameState; import cz.jzitnik.game.Player; import cz.jzitnik.game.ResourceManager; -import cz.jzitnik.game.utils.RoomCords; import cz.jzitnik.states.RenderState; import cz.jzitnik.states.ScreenBuffer; import cz.jzitnik.states.TerminalState; import cz.jzitnik.ui.pixels.ColoredPixel; import cz.jzitnik.ui.pixels.Pixel; import cz.jzitnik.utils.DependencyManager; +import cz.jzitnik.utils.RerenderUtils; import cz.jzitnik.utils.events.AbstractEventHandler; import cz.jzitnik.utils.events.EventManager; import lombok.extern.slf4j.Slf4j; @@ -66,26 +66,26 @@ public class FullRoomDrawHandler extends AbstractEventHandler { List partsToRerender = new ArrayList<>(); GameRoom currentRoom = gameState.getCurrentRoom(); - Set doorPositions = getDoorPositions(currentRoom); + Set doorPositions = RerenderUtils.getDoorPositions(currentRoom); var buffer = screenBuffer.getRenderedBuffer(); BufferedImage room = resourceManager.getResource(currentRoom.getTexture()); BufferedImage doors = resourceManager.getResource(ResourceManager.Resource.DOORS); Player player = gameState.getPlayer(); - BufferedImage playerTexture = getPlayer(resourceManager, player); + BufferedImage playerTexture = RerenderUtils.getPlayer(resourceManager, player); TerminalSize terminalSize = terminalScreen.getTerminalSize(); int width = room.getWidth(); int height = room.getHeight(); - var start = getStart(room, terminalSize); + var start = RerenderUtils.getStart(room, terminalSize); int startX = start.getX(); int startY = start.getY(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { - int pixel = getPixel(room, doors, doorPositions, player, playerTexture, x, y); + int pixel = RerenderUtils.getPixel(currentRoom, room, doors, doorPositions, player, playerTexture, x, y); int red = (pixel >> 16) & 0xff; int green = (pixel >> 8) & 0xff; int blue = pixel & 0xff; @@ -94,8 +94,6 @@ public class FullRoomDrawHandler extends AbstractEventHandler { buffer[y + startY][x * 2 + startX] = pixel1; buffer[y + startY][x * 2 + 1 + startX] = pixel1; - /*unrenderedBuffer[y + startY][x * 2 + startX].addFirst(pixel1); - unrenderedBuffer[y + startY][x * 2 + 1 + startX].addFirst(pixel1);*/ } } partsToRerender.add(new RerenderScreen.ScreenPart( @@ -110,68 +108,4 @@ public class FullRoomDrawHandler extends AbstractEventHandler { eventManager.emitEvent(new RerenderScreen(partsToRerender.toArray(RerenderScreen.ScreenPart[]::new))); } } - - public static RoomCords getStart(BufferedImage room, TerminalSize terminalSize) { - int width = room.getWidth(); - int height = room.getHeight(); - int terminalHeight = terminalSize.getRows(); - int terminalWidth = terminalSize.getColumns(); - - int x = (terminalWidth - (width * 2)) / 2; - int y = (terminalHeight - height) / 2; - - return new RoomCords(x, y); - } - - public static int getPixel(BufferedImage room, BufferedImage doors, Set doorPositions, Player player, BufferedImage playerTexture, int x, int y) { - 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 alpha = (pixel >> 24) & 0xff; - - if (alpha != 0) { - return pixel; - } - } - - record DoorBounds(int startX, int startY, int endX, int endY) { - boolean contains(int x, int y) { - return x >= startX && x <= endX && y >= startY && y <= endY; - } - } - - Map doorBounds = Map.of( - DoorPosition.TOP, new DoorBounds(96, 13, 132, 47), - DoorPosition.LEFT, new DoorBounds(0, 84, 37, 135), - DoorPosition.RIGHT, new DoorBounds(187, 98, 244, 136), - DoorPosition.BOTTOM, new DoorBounds(84, 190, 140, 225) - ); - - for (DoorPosition pos : doorPositions) { - DoorBounds bounds = doorBounds.get(pos); - if (bounds != null && bounds.contains(x, y)) { - return doors.getRGB(x, y); - } - } - - return room.getRGB(x, y); - } - - public static BufferedImage getPlayer(ResourceManager resourceManager, Player player) { - return resourceManager.getResource(switch (player.getPlayerRotation()) { - case FRONT -> ResourceManager.Resource.PLAYER_FRONT; - case BACK -> ResourceManager.Resource.PLAYER_BACK; - case LEFT -> ResourceManager.Resource.PLAYER_LEFT; - case RIGHT -> ResourceManager.Resource.PLAYER_RIGHT; - }); - } - - public static Set getDoorPositions(GameRoom currentRoom) { - Set doorPositions = new HashSet<>(); - if (currentRoom.getLeft() != null) doorPositions.add(DoorPosition.LEFT); - if (currentRoom.getRight() != null) doorPositions.add(DoorPosition.RIGHT); - if (currentRoom.getUp() != null) doorPositions.add(DoorPosition.TOP); - if (currentRoom.getDown() != null) doorPositions.add(DoorPosition.BOTTOM); - - return doorPositions; - } } diff --git a/src/main/java/cz/jzitnik/events/handlers/MouseActionEventHandler.java b/src/main/java/cz/jzitnik/events/handlers/MouseActionEventHandler.java index 8511bad..bf794a0 100644 --- a/src/main/java/cz/jzitnik/events/handlers/MouseActionEventHandler.java +++ b/src/main/java/cz/jzitnik/events/handlers/MouseActionEventHandler.java @@ -1,9 +1,12 @@ package cz.jzitnik.events.handlers; import cz.jzitnik.annotations.EventHandler; +import cz.jzitnik.annotations.injectors.InjectDependency; import cz.jzitnik.events.MouseAction; +import cz.jzitnik.events.MouseMoveEvent; import cz.jzitnik.utils.DependencyManager; import cz.jzitnik.utils.events.AbstractEventHandler; +import cz.jzitnik.utils.events.EventManager; @EventHandler(MouseAction.class) public class MouseActionEventHandler extends AbstractEventHandler { @@ -11,7 +14,13 @@ public class MouseActionEventHandler extends AbstractEventHandler { super(dm); } + @InjectDependency + private EventManager eventManager; + @Override public void handle(MouseAction event) { + switch (event.getActionType()) { + case MOVE -> eventManager.emitEvent(new MouseMoveEvent(event)); + } } } diff --git a/src/main/java/cz/jzitnik/events/handlers/MouseMoveEventHandler.java b/src/main/java/cz/jzitnik/events/handlers/MouseMoveEventHandler.java new file mode 100644 index 0000000..3ea861c --- /dev/null +++ b/src/main/java/cz/jzitnik/events/handlers/MouseMoveEventHandler.java @@ -0,0 +1,126 @@ +package cz.jzitnik.events.handlers; + +import com.googlecode.lanterna.TerminalPosition; +import cz.jzitnik.annotations.EventHandler; +import cz.jzitnik.annotations.injectors.InjectDependency; +import cz.jzitnik.annotations.injectors.InjectState; +import cz.jzitnik.events.MouseAction; +import cz.jzitnik.events.MouseMoveEvent; +import cz.jzitnik.events.RerenderScreen; +import cz.jzitnik.game.GameRoom; +import cz.jzitnik.game.GameState; +import cz.jzitnik.game.Player; +import cz.jzitnik.game.ResourceManager; +import cz.jzitnik.game.objects.GameObject; +import cz.jzitnik.game.utils.RoomCords; +import cz.jzitnik.states.ScreenBuffer; +import cz.jzitnik.states.TerminalState; +import cz.jzitnik.utils.DependencyManager; +import cz.jzitnik.utils.RerenderUtils; +import cz.jzitnik.utils.events.AbstractEventHandler; +import cz.jzitnik.utils.events.EventManager; +import lombok.extern.slf4j.Slf4j; + +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +@Slf4j +@EventHandler(MouseMoveEvent.class) +public class MouseMoveEventHandler extends AbstractEventHandler { + public MouseMoveEventHandler(DependencyManager dm) { + super(dm); + } + + @InjectState + private GameState gameState; + + @InjectState + private ScreenBuffer screenBuffer; + + @InjectState + private TerminalState terminalState; + + @InjectDependency + private ResourceManager resourceManager; + + @InjectDependency + private EventManager eventManager; + + @Override + public void handle(MouseMoveEvent event) { + MouseAction mouseAction = event.getMouseAction(); + int mouseX = mouseAction.getPosition().getColumn(); + int mouseY = mouseAction.getPosition().getRow(); + + 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(); + + Set selectedObjects = currentRoom.getObjects().stream().filter(gameObject -> { + if (!gameObject.isSelectable()) return false; + BufferedImage texture = gameObject.getTexture(); + RoomCords cords = gameObject.getCords(); + return + (mouseX - startX) / 2 >= cords.getX() && + (mouseX - startX) / 2 < cords.getX() + texture.getWidth() && + mouseY >= cords.getY() + startY && + mouseY < cords.getY() + startY + texture.getHeight(); + }).collect(Collectors.toSet()); + + Set changedObjects = new HashSet<>(); + + for (GameObject object : currentRoom.getObjects()) { + boolean newValue = selectedObjects.contains(object); + boolean changed = object.isSelected() != newValue; + + if (changed) { + object.setSelected(newValue); + changedObjects.add(object); + } + } + + List parts = new ArrayList<>(); + + for (GameObject object : changedObjects) { + RoomCords cords = object.getCords(); + BufferedImage objectTexture = object.getTexture(); + Player player = gameState.getPlayer(); + BufferedImage playerTexture = RerenderUtils.getPlayer(resourceManager, player); + + int forStartX = cords.getX(); + int forStartY = cords.getY(); + int forEndX = cords.getX() + objectTexture.getWidth() - 1; + int forEndY = cords.getY() + objectTexture.getHeight() - 1; + + RerenderUtils.rerenderPart( + forStartX, + forEndX, + forStartY, + forEndY, + startX, + startY, + currentRoom, + room, + player, + playerTexture, + screenBuffer, + resourceManager + ); + + parts.add(new RerenderScreen.ScreenPart( + new TerminalPosition(forStartX, forStartY), + new TerminalPosition(forEndX * 2 + 1 + startX, forEndY + startY) + )); + } + + if (!parts.isEmpty()) { + eventManager.emitEvent(new RerenderScreen(parts.toArray(RerenderScreen.ScreenPart[]::new))); + } + } +} diff --git a/src/main/java/cz/jzitnik/events/handlers/PlayerMoveEventHandler.java b/src/main/java/cz/jzitnik/events/handlers/PlayerMoveEventHandler.java index 6b45ff9..c41b323 100644 --- a/src/main/java/cz/jzitnik/events/handlers/PlayerMoveEventHandler.java +++ b/src/main/java/cz/jzitnik/events/handlers/PlayerMoveEventHandler.java @@ -1,12 +1,10 @@ package cz.jzitnik.events.handlers; import com.googlecode.lanterna.TerminalPosition; -import com.googlecode.lanterna.TextColor; import com.googlecode.lanterna.input.KeyStroke; import cz.jzitnik.annotations.EventHandler; import cz.jzitnik.annotations.injectors.InjectDependency; import cz.jzitnik.annotations.injectors.InjectState; -import cz.jzitnik.events.FullRoomDraw; import cz.jzitnik.events.PlayerMoveEvent; import cz.jzitnik.events.RerenderScreen; import cz.jzitnik.game.GameRoom; @@ -16,9 +14,8 @@ import cz.jzitnik.game.ResourceManager; import cz.jzitnik.game.utils.RoomCords; import cz.jzitnik.states.ScreenBuffer; import cz.jzitnik.states.TerminalState; -import cz.jzitnik.ui.pixels.ColoredPixel; -import cz.jzitnik.ui.pixels.Pixel; import cz.jzitnik.utils.DependencyManager; +import cz.jzitnik.utils.RerenderUtils; import cz.jzitnik.utils.events.AbstractEventHandler; import cz.jzitnik.utils.events.EventManager; import lombok.extern.slf4j.Slf4j; @@ -76,36 +73,19 @@ public class PlayerMoveEventHandler extends AbstractEventHandler doorPositions = FullRoomDrawHandler.getDoorPositions(currentRoom); - var buffer = screenBuffer.getRenderedBuffer(); - var start = FullRoomDrawHandler.getStart(room, terminalState.getTerminalScreen().getTerminalSize()); - int startX = start.getX(); - int startY = start.getY(); - + BufferedImage playerTexture = RerenderUtils.getPlayer(resourceManager, player); int forStartX = Math.min(originalPlayerX, newPlayerX); int forStartY = Math.min(originalPlayerY, newPlayerY); int forEndX = Math.max(originalPlayerX, newPlayerX) + playerTexture.getWidth(); int forEndY = Math.max(originalPlayerY, newPlayerY) + playerTexture.getHeight(); - for (int x = forStartX; x <= forEndX; x++) { - for (int y = forStartY; y <= forEndY; y++) { - int pixel = FullRoomDrawHandler.getPixel(room, doors, doorPositions, player, playerTexture, x, y); + 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(); - int red = (pixel >> 16) & 0xff; - int green = (pixel >> 8) & 0xff; - int blue = pixel & 0xff; - - Pixel pixel1 = new ColoredPixel(new TextColor.RGB(red, green, blue)); - - buffer[y + startY][x * 2 + startX] = pixel1; - buffer[y + startY][x * 2 + 1 + startX] = pixel1; - } - } + RerenderUtils.rerenderPart(forStartX, forEndX, forStartY, forEndY, startX, startY, currentRoom, room, player, playerTexture, screenBuffer, resourceManager); eventManager.emitEvent(new RerenderScreen( new RerenderScreen.ScreenPart( diff --git a/src/main/java/cz/jzitnik/game/GameRoom.java b/src/main/java/cz/jzitnik/game/GameRoom.java index f4dfb6d..e093aca 100644 --- a/src/main/java/cz/jzitnik/game/GameRoom.java +++ b/src/main/java/cz/jzitnik/game/GameRoom.java @@ -1,19 +1,26 @@ package cz.jzitnik.game; import cz.jzitnik.game.objects.GameObject; -import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import java.util.ArrayList; import java.util.List; -@AllArgsConstructor +@RequiredArgsConstructor @Getter +@Setter public class GameRoom { private GameRoom left; private GameRoom right; private GameRoom up; private GameRoom down; - private ResourceManager.Resource texture; + private final ResourceManager.Resource texture; - private List objects; + private final List objects = new ArrayList<>(); + + public void addObject(GameObject gameObject) { + objects.addFirst(gameObject); + } } diff --git a/src/main/java/cz/jzitnik/game/GameSetup.java b/src/main/java/cz/jzitnik/game/GameSetup.java index f895809..d9b2806 100644 --- a/src/main/java/cz/jzitnik/game/GameSetup.java +++ b/src/main/java/cz/jzitnik/game/GameSetup.java @@ -1,25 +1,31 @@ package cz.jzitnik.game; import cz.jzitnik.annotations.Dependency; +import cz.jzitnik.annotations.injectors.InjectDependency; import cz.jzitnik.annotations.injectors.InjectState; +import cz.jzitnik.game.objects.Chest; import cz.jzitnik.game.utils.RoomCords; -import java.util.ArrayList; - @Dependency public class GameSetup { @InjectState private GameState gameState; + @InjectDependency + private ResourceManager resourceManager; + public void setup() { - GameRoom mainRoom = new GameRoom( - null, null, null, null, - ResourceManager.Resource.ROOM1, - new ArrayList<>() - ); + GameRoom mainRoom = new GameRoom(ResourceManager.Resource.ROOM1); + GameRoom rightRoom = new GameRoom(ResourceManager.Resource.ROOM2); + + mainRoom.setRight(rightRoom); + rightRoom.setLeft(mainRoom); + + Chest chest = new Chest(resourceManager, new RoomCords(100, 45)); + mainRoom.addObject(chest); gameState.setCurrentRoom(mainRoom); - gameState.setPlayer(new Player(new RoomCords(155, 110))); + gameState.setPlayer(new Player(new RoomCords(90, 100))); } } diff --git a/src/main/java/cz/jzitnik/game/ResourceManager.java b/src/main/java/cz/jzitnik/game/ResourceManager.java index b76d7f5..1caae57 100644 --- a/src/main/java/cz/jzitnik/game/ResourceManager.java +++ b/src/main/java/cz/jzitnik/game/ResourceManager.java @@ -30,6 +30,8 @@ public class ResourceManager { PLAYER_LEFT("player/left.png"), PLAYER_RIGHT("player/right.png"), + CHEST("chest.png"), + DOORS("rooms/doors.png"); private final String path; diff --git a/src/main/java/cz/jzitnik/game/objects/Chest.java b/src/main/java/cz/jzitnik/game/objects/Chest.java index 1b07ddf..5b1a128 100644 --- a/src/main/java/cz/jzitnik/game/objects/Chest.java +++ b/src/main/java/cz/jzitnik/game/objects/Chest.java @@ -1,10 +1,10 @@ package cz.jzitnik.game.objects; +import cz.jzitnik.game.ResourceManager; import cz.jzitnik.game.utils.RoomCords; -import cz.jzitnik.ui.pixels.Pixel; public final class Chest extends GameObject { - public Chest(Pixel[][] texture, RoomCords cords) { - super(texture, cords); + public Chest(ResourceManager resourceManager, RoomCords cords) { + super(resourceManager.getResource(ResourceManager.Resource.CHEST), cords, true); } } diff --git a/src/main/java/cz/jzitnik/game/objects/GameObject.java b/src/main/java/cz/jzitnik/game/objects/GameObject.java index 86ce3de..5488f78 100644 --- a/src/main/java/cz/jzitnik/game/objects/GameObject.java +++ b/src/main/java/cz/jzitnik/game/objects/GameObject.java @@ -2,13 +2,19 @@ package cz.jzitnik.game.objects; import cz.jzitnik.game.utils.Renderable; import cz.jzitnik.game.utils.RoomCords; -import cz.jzitnik.ui.pixels.Pixel; -import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +import java.awt.image.BufferedImage; @Getter -@AllArgsConstructor +@RequiredArgsConstructor public sealed abstract class GameObject implements Renderable permits Chest { - private Pixel[][] texture; - private RoomCords cords; + private final BufferedImage texture; + private final RoomCords cords; + private final boolean selectable; + + @Setter + private boolean selected = false; } diff --git a/src/main/java/cz/jzitnik/game/utils/Renderable.java b/src/main/java/cz/jzitnik/game/utils/Renderable.java index 771f958..c39e169 100644 --- a/src/main/java/cz/jzitnik/game/utils/Renderable.java +++ b/src/main/java/cz/jzitnik/game/utils/Renderable.java @@ -1,7 +1,7 @@ package cz.jzitnik.game.utils; -import cz.jzitnik.ui.pixels.Pixel; +import java.awt.image.BufferedImage; public interface Renderable { - Pixel[][] getTexture(); + BufferedImage getTexture(); } diff --git a/src/main/java/cz/jzitnik/game/utils/RoomCords.java b/src/main/java/cz/jzitnik/game/utils/RoomCords.java index 58a4c87..b113a63 100644 --- a/src/main/java/cz/jzitnik/game/utils/RoomCords.java +++ b/src/main/java/cz/jzitnik/game/utils/RoomCords.java @@ -1,7 +1,9 @@ package cz.jzitnik.game.utils; import lombok.Getter; +import lombok.ToString; +@ToString @Getter public class RoomCords { private int x; diff --git a/src/main/java/cz/jzitnik/utils/RerenderUtils.java b/src/main/java/cz/jzitnik/utils/RerenderUtils.java new file mode 100644 index 0000000..9917523 --- /dev/null +++ b/src/main/java/cz/jzitnik/utils/RerenderUtils.java @@ -0,0 +1,130 @@ +package cz.jzitnik.utils; + +import com.googlecode.lanterna.TerminalSize; +import com.googlecode.lanterna.TextColor; +import cz.jzitnik.events.handlers.FullRoomDrawHandler; +import cz.jzitnik.game.GameRoom; +import cz.jzitnik.game.Player; +import cz.jzitnik.game.ResourceManager; +import cz.jzitnik.game.objects.GameObject; +import cz.jzitnik.game.utils.RoomCords; +import cz.jzitnik.states.ScreenBuffer; +import cz.jzitnik.ui.pixels.ColoredPixel; +import cz.jzitnik.ui.pixels.Pixel; + +import java.awt.image.BufferedImage; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class RerenderUtils { + public static RoomCords getStart(BufferedImage room, TerminalSize terminalSize) { + int width = room.getWidth(); + int height = room.getHeight(); + int terminalHeight = terminalSize.getRows(); + int terminalWidth = terminalSize.getColumns(); + + int x = (terminalWidth - (width * 2)) / 2; + int y = (terminalHeight - height) / 2; + + 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) { + var buffer = screenBuffer.getRenderedBuffer(); + BufferedImage doors = resourceManager.getResource(ResourceManager.Resource.DOORS); + Set doorPositions = RerenderUtils.getDoorPositions(currentRoom); + for (int x = startX; x <= endX; x++) { + for (int y = startY; y <= endY; y++) { + int pixel = getPixel(currentRoom, room, doors, doorPositions, player, playerTexture, x, y); + + int red = (pixel >> 16) & 0xff; + int green = (pixel >> 8) & 0xff; + int blue = pixel & 0xff; + + Pixel pixel1 = new ColoredPixel(new TextColor.RGB(red, green, blue)); + + buffer[y + screenStartY][x * 2 + screenStartX] = pixel1; + buffer[y + screenStartY][x * 2 + 1 + screenStartX] = pixel1; + } + } + } + + public static int getPixel(GameRoom currentRoom, BufferedImage room, BufferedImage doors, Set doorPositions, Player player, BufferedImage playerTexture, int x, int y) { + 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 alpha = (pixel >> 24) & 0xff; + + if (alpha != 0) { + return pixel; + } + } + + for (GameObject object : currentRoom.getObjects()) { + RoomCords startObjectCords = object.getCords(); + BufferedImage texture = object.getTexture(); + RoomCords endObjectCords = new RoomCords(startObjectCords.getX() + texture.getWidth() - 1, startObjectCords.getY() + texture.getHeight() - 1); + + if (x >= startObjectCords.getX() && x <= endObjectCords.getX() && y >= startObjectCords.getY() && y <= endObjectCords.getY()) { + int pixel = texture.getRGB(x - startObjectCords.getX(), y - startObjectCords.getY()); + int alpha = (pixel >> 24) & 0xff; + int r = (pixel >> 16) & 0xff; + int g = (pixel >> 8) & 0xff; + int b = pixel & 0xff; + float factor = 1.5f; // brightness multiplier + + if (alpha != 0) { + if (object.isSelected()) { + r = Math.min(255, (int)(r * factor)); + g = Math.min(255, (int)(g * factor)); + b = Math.min(255, (int)(b * factor)); + pixel = (alpha << 24) | (r << 16) | (g << 8) | b; + } + + return pixel; + } + } + } + + record DoorBounds(int startX, int startY, int endX, int endY) { + boolean contains(int x, int y) { + return x >= startX && x <= endX && y >= startY && y <= endY; + } + } + + Map doorBounds = Map.of( + FullRoomDrawHandler.DoorPosition.TOP, new DoorBounds(96, 13, 132, 47), + FullRoomDrawHandler.DoorPosition.LEFT, new DoorBounds(0, 84, 37, 135), + FullRoomDrawHandler.DoorPosition.RIGHT, new DoorBounds(187, 98, 244, 136), + FullRoomDrawHandler.DoorPosition.BOTTOM, new DoorBounds(84, 190, 140, 225) + ); + + for (FullRoomDrawHandler.DoorPosition pos : doorPositions) { + DoorBounds bounds = doorBounds.get(pos); + if (bounds != null && bounds.contains(x, y)) { + return doors.getRGB(x, y); + } + } + + return room.getRGB(x, y); + } + + public static BufferedImage getPlayer(ResourceManager resourceManager, Player player) { + return resourceManager.getResource(switch (player.getPlayerRotation()) { + case FRONT -> ResourceManager.Resource.PLAYER_FRONT; + case BACK -> ResourceManager.Resource.PLAYER_BACK; + case LEFT -> ResourceManager.Resource.PLAYER_LEFT; + case RIGHT -> ResourceManager.Resource.PLAYER_RIGHT; + }); + } + + public static Set getDoorPositions(GameRoom currentRoom) { + Set doorPositions = new HashSet<>(); + if (currentRoom.getLeft() != null) doorPositions.add(FullRoomDrawHandler.DoorPosition.LEFT); + if (currentRoom.getRight() != null) doorPositions.add(FullRoomDrawHandler.DoorPosition.RIGHT); + if (currentRoom.getUp() != null) doorPositions.add(FullRoomDrawHandler.DoorPosition.TOP); + if (currentRoom.getDown() != null) doorPositions.add(FullRoomDrawHandler.DoorPosition.BOTTOM); + + return doorPositions; + } +} diff --git a/src/main/resources/textures/chest.png b/src/main/resources/textures/chest.png new file mode 100644 index 0000000..49d877c Binary files /dev/null and b/src/main/resources/textures/chest.png differ