From f8bc960af203aae4e4aebbff341d03d245548d5e Mon Sep 17 00:00:00 2001 From: jzitnik-dev Date: Fri, 2 Jan 2026 17:34:44 +0100 Subject: [PATCH] feat: Better colors for inventory --- .../handlers/MouseActionEventHandler.java | 2 - src/main/java/cz/jzitnik/game/Player.java | 2 + .../java/cz/jzitnik/game/objects/Chest.java | 8 +- src/main/java/cz/jzitnik/ui/Inventory.java | 87 ++++++++++++++++--- .../utils/roomtasks/RoomTaskScheduler.java | 4 +- 5 files changed, 80 insertions(+), 23 deletions(-) diff --git a/src/main/java/cz/jzitnik/events/handlers/MouseActionEventHandler.java b/src/main/java/cz/jzitnik/events/handlers/MouseActionEventHandler.java index eb15a12..e2f49b7 100644 --- a/src/main/java/cz/jzitnik/events/handlers/MouseActionEventHandler.java +++ b/src/main/java/cz/jzitnik/events/handlers/MouseActionEventHandler.java @@ -8,8 +8,6 @@ import cz.jzitnik.config.PlayerConfig; import cz.jzitnik.events.MouseAction; import cz.jzitnik.events.MouseMoveEvent; import cz.jzitnik.game.GameState; -import cz.jzitnik.game.objects.GameObject; -import cz.jzitnik.game.objects.Interactable; import cz.jzitnik.game.utils.Selectable; import cz.jzitnik.states.RenderState; import cz.jzitnik.utils.DependencyManager; diff --git a/src/main/java/cz/jzitnik/game/Player.java b/src/main/java/cz/jzitnik/game/Player.java index 88f8dee..57733d5 100644 --- a/src/main/java/cz/jzitnik/game/Player.java +++ b/src/main/java/cz/jzitnik/game/Player.java @@ -19,6 +19,8 @@ public class Player { private final RoomCords playerCords; private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); private final GameItem[] inventory = new GameItem[Inventory.ITEMS_X * Inventory.ITEMS_Y]; + @Setter + private GameItem selectedItem; private boolean swinging = false; public boolean addItem(GameItem item) { diff --git a/src/main/java/cz/jzitnik/game/objects/Chest.java b/src/main/java/cz/jzitnik/game/objects/Chest.java index 1b632d3..8ce176a 100644 --- a/src/main/java/cz/jzitnik/game/objects/Chest.java +++ b/src/main/java/cz/jzitnik/game/objects/Chest.java @@ -18,6 +18,7 @@ import cz.jzitnik.game.items.GameItem; import cz.jzitnik.game.utils.RoomCords; import cz.jzitnik.states.ScreenBuffer; import cz.jzitnik.states.TerminalState; +import cz.jzitnik.ui.Inventory; import cz.jzitnik.ui.utils.Grid; import cz.jzitnik.ui.pixels.ColoredPixel; import cz.jzitnik.ui.pixels.Empty; @@ -35,9 +36,6 @@ import java.util.List; @Slf4j public final class Chest extends GameObject implements UIClickHandler { - private static final TextColor BORDER_COLOR = new TextColor.RGB(255, 255, 255); - private static final TextColor TRANSPARENT_COLOR = new TextColor.RGB(166, 166, 166); - private static final int RENDER_PADDING = 1; private final List items; @@ -91,8 +89,8 @@ public final class Chest extends GameObject implements UIClickHandler { 2, // Inner Border 16, // Item Size 1, // Item Padding (Changed to 1 as per your request example) - new ColoredPixel(BORDER_COLOR), - new ColoredPixel(TRANSPARENT_COLOR) + Inventory.BORDER_COLOR, + Inventory.BACKGROUND_COLOR ); } diff --git a/src/main/java/cz/jzitnik/ui/Inventory.java b/src/main/java/cz/jzitnik/ui/Inventory.java index 6bb509c..6b468b0 100644 --- a/src/main/java/cz/jzitnik/ui/Inventory.java +++ b/src/main/java/cz/jzitnik/ui/Inventory.java @@ -20,26 +20,37 @@ import cz.jzitnik.ui.utils.Grid; import cz.jzitnik.utils.RerenderUtils; import cz.jzitnik.utils.events.EventManager; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; import java.awt.image.BufferedImage; import java.util.Arrays; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; +@Slf4j @Dependency public class Inventory implements GlobalUIClickHandler { + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); public static final int ITEMS_X = 3; public static final int ITEMS_Y = 5; private static final int OUTER_BORDER_WIDTH = 2; private static final int INNER_BORDER_WIDTH = 1; private static final int ITEM_SIZE = 16; // Characters private static final int ITEM_PADDING = 2; // padding on each side - private static final Pixel BORDER_COLOR = - new ColoredPixel(new TextColor.RGB(255, 255, 255)); - private static final Pixel BACKGROUND_COLOR = - new ColoredPixel(new TextColor.RGB(166, 166, 166)); + public static final Pixel BORDER_COLOR = + new ColoredPixel(new TextColor.RGB(41, 29, 19)); + public static final Pixel BACKGROUND_COLOR = + new ColoredPixel(new TextColor.RGB(61, 45, 29)); private static final Pixel BACKGROUND_COLOR_HOVERED = - new ColoredPixel(new TextColor.RGB(186, 186, 186)); + new ColoredPixel(new TextColor.RGB(77, 56, 36)); private static final Pixel BACKGROUND_COLOR_SELECTED = - new ColoredPixel(new TextColor.RGB(216, 216, 216)); + new ColoredPixel(new TextColor.RGB(95, 62, 32)); + private static final Pixel BACKGROUND_COLOR_EQUIPPED = + new ColoredPixel(new TextColor.RGB(50, 145, 150)); + private static final Pixel BACKGROUND_COLOR_EQUIPPED_SELECTED = + new ColoredPixel(new TextColor.RGB(58, 170, 176)); private static final int ITEM_SLOT_SIZE = ITEM_SIZE + ITEM_PADDING * 2; public static final int INVENTORY_WIDTH = OUTER_BORDER_WIDTH * 2 + @@ -49,6 +60,7 @@ public class Inventory implements GlobalUIClickHandler { (ITEMS_Y * (ITEM_SLOT_SIZE + INNER_BORDER_WIDTH) - INNER_BORDER_WIDTH); private static final int REAL_INVENTORY_HEIGHT = Math.ceilDiv(INVENTORY_HEIGHT, 2); // 2 pixels per terminal row + private static final Grid grid = new Grid( ITEMS_X, ITEMS_Y, @@ -99,13 +111,15 @@ public class Inventory implements GlobalUIClickHandler { inventoryState.draggingItemPosition = null; inventoryState.selectedItem = -1; - if (itemClickedOnIndex != -1) { + if (itemClickedOnIndex != -1 && inventory[itemClickedOnIndex] == null) { inventory[itemClickedOnIndex] = gameItem; - inventoryState.hoveredItem = itemClickedOnIndex; } else { - gameState.getPlayer().addItem(gameItem); + inventory[inventoryState.draggingItemOriginalIndex] = gameItem; } + inventoryState.draggingItemOriginalIndex = -1; + inventoryState.hoveredItem = itemClickedOnIndex; + eventManager.emitEvent(new InventoryRerender()); return true; } @@ -120,10 +134,31 @@ public class Inventory implements GlobalUIClickHandler { return true; } + if (inventoryState.isGonnaDoubleclick) { + inventoryState.isGonnaDoubleclick = false; + inventoryState.selectedItem = -1; + gameState.getPlayer().setSelectedItem(inventory[itemClickedOnIndex]); + eventManager.emitEvent(new InventoryRerender()); + + return true; + } + + inventoryState.isGonnaDoubleclick = true; + log.debug("Gonna doubleclick: {}", true); + scheduler.schedule(() -> { + inventoryState.isGonnaDoubleclick = false; + log.debug("Gonna doubleclick: {}", false); + }, 200, TimeUnit.MILLISECONDS); + + if (inventoryState.selectedItem == itemClickedOnIndex) { inventoryState.selectedItem = -1; } else if (inventoryState.selectedItem == -1) { - inventoryState.selectedItem = itemClickedOnIndex; + if (inventory[itemClickedOnIndex] != null) { + inventoryState.selectedItem = itemClickedOnIndex; + } else { + return true; + } } else { // Already have selected item and now clicked on different item so swap items GameItem temp = inventory[inventoryState.selectedItem]; @@ -174,6 +209,7 @@ public class Inventory implements GlobalUIClickHandler { boolean render = false; if (inventoryState.onNextDragTakeItemOnIndex != -1) { inventoryState.draggingItem = gameState.getPlayer().getInventory()[inventoryState.onNextDragTakeItemOnIndex]; + inventoryState.draggingItemOriginalIndex = inventoryState.onNextDragTakeItemOnIndex; gameState.getPlayer().getInventory()[inventoryState.onNextDragTakeItemOnIndex] = null; inventoryState.onNextDragTakeItemOnIndex = -1; render = true; @@ -201,6 +237,11 @@ public class Inventory implements GlobalUIClickHandler { var inventory = gameState.getPlayer().getInventory(); var buffer = screenBuffer.getRenderedBuffer(); + int indexEquippedItem = IntStream.range(0, inventory.length) + .filter(i -> inventory[i] == gameState.getPlayer().getSelectedItem()) + .findFirst() + .orElse(-1); + BufferedImage[] textures = Arrays.stream(inventory) .map(item -> item == null ? null : item.getTexture()) .toArray(BufferedImage[]::new); @@ -212,6 +253,11 @@ public class Inventory implements GlobalUIClickHandler { if (inventoryState.selectedItem != -1) { backgrounds[inventoryState.selectedItem] = BACKGROUND_COLOR_SELECTED; } + if (indexEquippedItem != -1 && indexEquippedItem != inventoryState.selectedItem) { + backgrounds[indexEquippedItem] = BACKGROUND_COLOR_EQUIPPED; + } else if (indexEquippedItem != -1) { + backgrounds[indexEquippedItem] = BACKGROUND_COLOR_EQUIPPED_SELECTED; + } Pixel[][] internalBuffer = grid.render(textures, backgrounds); if (inventoryState.draggingItem != null) { @@ -229,13 +275,24 @@ public class Inventory implements GlobalUIClickHandler { for (int x = 0; x < texture.getWidth(); x++) { int pixel = texture.getRGB(x, y); int alpha = (pixel >> 24) & 0xff; - int r = (pixel >> 16) & 0xff; - int g = (pixel >> 8) & 0xff; - int b = pixel & 0xff; if (alpha == 0) { continue; } - internalBuffer[y + offsetY][x + offsetX] = new ColoredPixel(new TextColor.RGB(r, g, b)); + Pixel bottomPixel = internalBuffer[y + offsetY][x + offsetX]; + + int topR = (pixel >> 16) & 0xff; + int topG = (pixel >> 8) & 0xff; + int topB = pixel & 0xff; + float topOpacity = 0.80f; + int bottomR = bottomPixel.getColor().getRed(); + int bottomG = bottomPixel.getColor().getGreen(); + int bottomB = bottomPixel.getColor().getBlue(); + + int finalR = (int)(topR * topOpacity + bottomR * (1 - topOpacity)); + int finalG = (int)(topG * topOpacity + bottomG * (1 - topOpacity)); + int finalB = (int)(topB * topOpacity + bottomB * (1 - topOpacity)); + + internalBuffer[y + offsetY][x + offsetX] = new ColoredPixel(new TextColor.RGB(finalR, finalG, finalB)); } } } @@ -251,5 +308,7 @@ public class Inventory implements GlobalUIClickHandler { protected GameItem draggingItem; protected TerminalPosition draggingItemPosition; protected int onNextDragTakeItemOnIndex = -1; + protected int draggingItemOriginalIndex = -1; + protected boolean isGonnaDoubleclick = false; } } diff --git a/src/main/java/cz/jzitnik/utils/roomtasks/RoomTaskScheduler.java b/src/main/java/cz/jzitnik/utils/roomtasks/RoomTaskScheduler.java index b92e52d..2fb9834 100644 --- a/src/main/java/cz/jzitnik/utils/roomtasks/RoomTaskScheduler.java +++ b/src/main/java/cz/jzitnik/utils/roomtasks/RoomTaskScheduler.java @@ -19,13 +19,13 @@ import java.util.concurrent.TimeUnit; @Slf4j @Dependency public class RoomTaskScheduler { - ScheduledExecutorService scheduler; + private ScheduledExecutorService scheduler; @InjectConfig private ThreadPoolConfig threadPoolConfig; @InjectDependency private DependencyManager dependencyManager; - private HashMap> tasks = new HashMap<>(); + private final HashMap> tasks = new HashMap<>(); private boolean firstRun = true;