feat: Better colors for inventory

This commit is contained in:
2026-01-02 17:34:44 +01:00
parent b355ae1dd2
commit f8bc960af2
5 changed files with 80 additions and 23 deletions

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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<GameItem> 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
);
}

View File

@@ -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;
}
}

View File

@@ -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<RoomTask, ScheduledFuture<?>> tasks = new HashMap<>();
private final HashMap<RoomTask, ScheduledFuture<?>> tasks = new HashMap<>();
private boolean firstRun = true;