feat: New Grid API and Inventory rendered
This commit is contained in:
6
src/main/java/cz/jzitnik/events/InventoryRerender.java
Normal file
6
src/main/java/cz/jzitnik/events/InventoryRerender.java
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package cz.jzitnik.events;
|
||||||
|
|
||||||
|
import cz.jzitnik.utils.events.Event;
|
||||||
|
|
||||||
|
public class InventoryRerender implements Event {
|
||||||
|
}
|
||||||
@@ -78,6 +78,9 @@ public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
|
|||||||
int startY = start.getY();
|
int startY = start.getY();
|
||||||
|
|
||||||
RerenderUtils.rerenderPart(0, width - 1, 0, height - 1, startX, startY, currentRoom, room, player, playerTexture, screenBuffer, resourceManager, debugging);
|
RerenderUtils.rerenderPart(0, width - 1, 0, height - 1, startX, startY, currentRoom, room, player, playerTexture, screenBuffer, resourceManager, debugging);
|
||||||
|
if (event.isFullRerender()) {
|
||||||
|
InventoryRerenderHandler.renderInventoryRerender(dm);
|
||||||
|
}
|
||||||
|
|
||||||
partsToRerender.add(new RerenderScreen.ScreenPart(
|
partsToRerender.add(new RerenderScreen.ScreenPart(
|
||||||
new TerminalPosition(startX, startY),
|
new TerminalPosition(startX, startY),
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package cz.jzitnik.events.handlers;
|
||||||
|
|
||||||
|
import com.googlecode.lanterna.TerminalSize;
|
||||||
|
import com.googlecode.lanterna.TextColor;
|
||||||
|
import cz.jzitnik.annotations.EventHandler;
|
||||||
|
import cz.jzitnik.events.InventoryRerender;
|
||||||
|
import cz.jzitnik.game.GameRoom;
|
||||||
|
import cz.jzitnik.game.GameState;
|
||||||
|
import cz.jzitnik.game.ResourceManager;
|
||||||
|
import cz.jzitnik.game.items.GameItem;
|
||||||
|
import cz.jzitnik.states.ScreenBuffer;
|
||||||
|
import cz.jzitnik.states.TerminalState;
|
||||||
|
import cz.jzitnik.ui.Grid;
|
||||||
|
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.StateManager;
|
||||||
|
import cz.jzitnik.utils.events.AbstractEventHandler;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
@EventHandler(InventoryRerender.class)
|
||||||
|
public class InventoryRerenderHandler extends AbstractEventHandler<InventoryRerender> {
|
||||||
|
|
||||||
|
private static final int ITEMS_X = 3;
|
||||||
|
private static final int ITEMS_Y = 5;
|
||||||
|
private static final int OUTER_BORDER_WIDTH = 3;
|
||||||
|
private static final int INNER_BORDER_WIDTH = 2;
|
||||||
|
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));
|
||||||
|
|
||||||
|
private static final int ITEM_SLOT_SIZE = ITEM_SIZE + ITEM_PADDING * 2;
|
||||||
|
private static final int INVENTORY_WIDTH =
|
||||||
|
OUTER_BORDER_WIDTH * 2 +
|
||||||
|
(ITEMS_X * (ITEM_SLOT_SIZE + INNER_BORDER_WIDTH) - INNER_BORDER_WIDTH);
|
||||||
|
private static final int INVENTORY_HEIGHT =
|
||||||
|
OUTER_BORDER_WIDTH * 2 +
|
||||||
|
(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
|
||||||
|
|
||||||
|
public InventoryRerenderHandler(DependencyManager dm) {
|
||||||
|
super(dm);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void renderInventoryRerender(DependencyManager dm) {
|
||||||
|
StateManager stateManager = dm.getDependencyOrThrow(StateManager.class);
|
||||||
|
ResourceManager resourceManager = dm.getDependencyOrThrow(ResourceManager.class);
|
||||||
|
|
||||||
|
GameState gameState = stateManager.getOrThrow(GameState.class);
|
||||||
|
GameRoom currentRoom = gameState.getCurrentRoom();
|
||||||
|
BufferedImage room = resourceManager.getResource(currentRoom.getTexture());
|
||||||
|
|
||||||
|
TerminalState terminalState = stateManager.getOrThrow(TerminalState.class);
|
||||||
|
TerminalSize terminalSize = terminalState.getTerminalScreen().getTerminalSize();
|
||||||
|
|
||||||
|
var inventory = gameState.getPlayer().getInventory();
|
||||||
|
var buffer = stateManager.getOrThrow(ScreenBuffer.class).getRenderedBuffer();
|
||||||
|
|
||||||
|
var roomStart = RerenderUtils.getStart(room, terminalSize);
|
||||||
|
int maxX = roomStart.getX() - 1;
|
||||||
|
|
||||||
|
final int OFFSET_Y =
|
||||||
|
(((terminalSize.getRows() - 1) / 2) - (REAL_INVENTORY_HEIGHT / 2)) * 2;
|
||||||
|
final int OFFSET_X =
|
||||||
|
(maxX / 2) - (INVENTORY_WIDTH / 2);
|
||||||
|
|
||||||
|
BufferedImage[] textures = inventory.stream()
|
||||||
|
.map(GameItem::getTexture)
|
||||||
|
.toArray(BufferedImage[]::new);
|
||||||
|
|
||||||
|
Grid grid = new Grid(
|
||||||
|
ITEMS_X,
|
||||||
|
ITEMS_Y,
|
||||||
|
OUTER_BORDER_WIDTH,
|
||||||
|
INNER_BORDER_WIDTH,
|
||||||
|
ITEM_SIZE,
|
||||||
|
ITEM_PADDING,
|
||||||
|
BORDER_COLOR,
|
||||||
|
BACKGROUND_COLOR
|
||||||
|
);
|
||||||
|
|
||||||
|
Pixel[][] internalBuffer = grid.render(textures);
|
||||||
|
|
||||||
|
for (int y = 0; y < grid.getHeight(); y++) {
|
||||||
|
System.arraycopy(internalBuffer[y], 0, buffer[y + OFFSET_Y], OFFSET_X, grid.getWidth());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(InventoryRerender event) {
|
||||||
|
renderInventoryRerender(dm);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,13 +5,16 @@ import cz.jzitnik.annotations.EventHandler;
|
|||||||
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.events.ExitEvent;
|
import cz.jzitnik.events.ExitEvent;
|
||||||
|
import cz.jzitnik.events.FullRoomDraw;
|
||||||
import cz.jzitnik.events.KeyboardPressEvent;
|
import cz.jzitnik.events.KeyboardPressEvent;
|
||||||
import cz.jzitnik.events.PlayerMoveEvent;
|
import cz.jzitnik.events.PlayerMoveEvent;
|
||||||
import cz.jzitnik.game.GameState;
|
import cz.jzitnik.game.GameState;
|
||||||
import cz.jzitnik.utils.DependencyManager;
|
import cz.jzitnik.utils.DependencyManager;
|
||||||
import cz.jzitnik.utils.events.AbstractEventHandler;
|
import cz.jzitnik.utils.events.AbstractEventHandler;
|
||||||
import cz.jzitnik.utils.events.EventManager;
|
import cz.jzitnik.utils.events.EventManager;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@EventHandler(KeyboardPressEvent.class)
|
@EventHandler(KeyboardPressEvent.class)
|
||||||
public class KeyboardPressEventHandler extends AbstractEventHandler<KeyboardPressEvent> {
|
public class KeyboardPressEventHandler extends AbstractEventHandler<KeyboardPressEvent> {
|
||||||
public KeyboardPressEventHandler(DependencyManager dm) {
|
public KeyboardPressEventHandler(DependencyManager dm) {
|
||||||
@@ -37,6 +40,10 @@ public class KeyboardPressEventHandler extends AbstractEventHandler<KeyboardPres
|
|||||||
case Escape:
|
case Escape:
|
||||||
eventManager.emitEvent(new ExitEvent());
|
eventManager.emitEvent(new ExitEvent());
|
||||||
break;
|
break;
|
||||||
|
case F5:
|
||||||
|
log.debug("Fully rerendering screen");
|
||||||
|
eventManager.emitEvent(new FullRoomDraw(true));
|
||||||
|
break;
|
||||||
case Character:
|
case Character:
|
||||||
switch (keyStroke.getCharacter()) {
|
switch (keyStroke.getCharacter()) {
|
||||||
case 'w','a','s','d' -> eventManager.emitEvent(new PlayerMoveEvent(keyStroke));
|
case 'w','a','s','d' -> eventManager.emitEvent(new PlayerMoveEvent(keyStroke));
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ public class GameRoom {
|
|||||||
for (int x = 0; x < width; x++) {
|
for (int x = 0; x < width; x++) {
|
||||||
for (int y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
overrideBuffer[y][x] = new Empty();
|
overrideBuffer[y][x] = new Empty();
|
||||||
overrideBuffer[y][x] = new Empty();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import cz.jzitnik.game.items.GameItem;
|
|||||||
import cz.jzitnik.game.utils.RoomCords;
|
import cz.jzitnik.game.utils.RoomCords;
|
||||||
import cz.jzitnik.states.ScreenBuffer;
|
import cz.jzitnik.states.ScreenBuffer;
|
||||||
import cz.jzitnik.states.TerminalState;
|
import cz.jzitnik.states.TerminalState;
|
||||||
|
import cz.jzitnik.ui.Grid;
|
||||||
import cz.jzitnik.ui.pixels.ColoredPixel;
|
import cz.jzitnik.ui.pixels.ColoredPixel;
|
||||||
import cz.jzitnik.ui.pixels.Empty;
|
import cz.jzitnik.ui.pixels.Empty;
|
||||||
import cz.jzitnik.ui.pixels.Pixel;
|
import cz.jzitnik.ui.pixels.Pixel;
|
||||||
@@ -33,8 +34,10 @@ import java.util.List;
|
|||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public final class Chest extends GameObject implements UIClickHandler {
|
public final class Chest extends GameObject implements UIClickHandler {
|
||||||
private static final TextColor BORDER_COLOR = new TextColor.RGB(0, 0, 0);
|
private static final TextColor BORDER_COLOR = new TextColor.RGB(255, 255, 255);
|
||||||
private static final TextColor TRANSPARENT_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;
|
private final List<GameItem> items;
|
||||||
private final DependencyManager dependencyManager;
|
private final DependencyManager dependencyManager;
|
||||||
@@ -43,6 +46,7 @@ public final class Chest extends GameObject implements UIClickHandler {
|
|||||||
|
|
||||||
private int actualDisplayStartX;
|
private int actualDisplayStartX;
|
||||||
private int actualDisplayStartY;
|
private int actualDisplayStartY;
|
||||||
|
|
||||||
private int chestUISizeX;
|
private int chestUISizeX;
|
||||||
private int chestUISizeY;
|
private int chestUISizeY;
|
||||||
|
|
||||||
@@ -78,6 +82,19 @@ public final class Chest extends GameObject implements UIClickHandler {
|
|||||||
render(false);
|
render(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Grid createGrid(int itemCount) {
|
||||||
|
return new Grid(
|
||||||
|
Math.max(1, itemCount), // Items X
|
||||||
|
1, // Items Y
|
||||||
|
2, // Outer Border
|
||||||
|
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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private void render(boolean clear) {
|
private void render(boolean clear) {
|
||||||
GameRoom currentRoom = gameState.getCurrentRoom();
|
GameRoom currentRoom = gameState.getCurrentRoom();
|
||||||
Player player = gameState.getPlayer();
|
Player player = gameState.getPlayer();
|
||||||
@@ -94,8 +111,9 @@ public final class Chest extends GameObject implements UIClickHandler {
|
|||||||
terminalState.getTerminalScreen().getTerminalSize()
|
terminalState.getTerminalScreen().getTerminalSize()
|
||||||
);
|
);
|
||||||
|
|
||||||
int itemCount = items.size();
|
Grid currentGrid = createGrid(items.size());
|
||||||
calculateUISize(itemCount);
|
this.chestUISizeX = currentGrid.getWidth();
|
||||||
|
this.chestUISizeY = currentGrid.getHeight();
|
||||||
|
|
||||||
int chestUIStartX = getCords().getX();
|
int chestUIStartX = getCords().getX();
|
||||||
int chestUIStartY = getCords().getY();
|
int chestUIStartY = getCords().getY();
|
||||||
@@ -103,39 +121,39 @@ public final class Chest extends GameObject implements UIClickHandler {
|
|||||||
int guiStartX = chestUIStartX + (chestTexture.getWidth() / 2) - (chestUISizeX / 2);
|
int guiStartX = chestUIStartX + (chestTexture.getWidth() / 2) - (chestUISizeX / 2);
|
||||||
int guiStartY = chestUIStartY - chestUISizeY - 1;
|
int guiStartY = chestUIStartY - chestUISizeY - 1;
|
||||||
|
|
||||||
TerminalPosition guiStart = new TerminalPosition(guiStartX + start.getX(), guiStartY + start.getY());
|
actualDisplayStartX = guiStartX + start.getX();
|
||||||
TerminalPosition guiEnd = new TerminalPosition(
|
actualDisplayStartY = guiStartY + start.getY();
|
||||||
(guiStartX + chestUISizeX - 1) + start.getX(),
|
|
||||||
(guiStartY + chestUISizeY - 1) + start.getY()
|
|
||||||
);
|
|
||||||
|
|
||||||
actualDisplayStartX = guiStartX + start.getX() + 2;
|
int renderMinX = actualDisplayStartX;
|
||||||
actualDisplayStartY = guiStartY + start.getY() + 2;
|
int renderMinY = actualDisplayStartY;
|
||||||
|
int renderMaxX = actualDisplayStartX + chestUISizeX;
|
||||||
|
int renderMaxY = actualDisplayStartY + chestUISizeY;
|
||||||
|
|
||||||
if (clear) {
|
if (clear) {
|
||||||
|
Grid previousGrid = createGrid(items.size() + 1);
|
||||||
|
int prevWidth = previousGrid.getWidth();
|
||||||
|
|
||||||
|
int prevGuiStartX = chestUIStartX + (chestTexture.getWidth() / 2) - (prevWidth / 2);
|
||||||
|
int prevDisplayStartX = prevGuiStartX + start.getX();
|
||||||
|
|
||||||
|
renderMinX = Math.min(renderMinX, prevDisplayStartX);
|
||||||
|
renderMaxX = Math.max(renderMaxX, prevDisplayStartX + prevWidth);
|
||||||
|
|
||||||
clearPreviousUI(
|
clearPreviousUI(
|
||||||
currentRoom,
|
currentRoom, roomTexture, player, playerTexture,
|
||||||
roomTexture,
|
buffer, overrideBuffer, start,
|
||||||
player,
|
|
||||||
playerTexture,
|
|
||||||
buffer,
|
|
||||||
overrideBuffer,
|
|
||||||
start,
|
|
||||||
guiStartY,
|
guiStartY,
|
||||||
chestUIStartX,
|
prevGuiStartX,
|
||||||
chestTexture.getWidth(),
|
prevWidth,
|
||||||
itemCount
|
chestUISizeY
|
||||||
);
|
);
|
||||||
|
|
||||||
int clearWidth = 4 + (itemCount + 1) * 16 + itemCount * 2;
|
|
||||||
int clearStartX = chestUIStartX + (chestTexture.getWidth() / 2) - (clearWidth / 2);
|
|
||||||
|
|
||||||
guiStart = new TerminalPosition(clearStartX + start.getX(), guiStartY + start.getY());
|
|
||||||
guiEnd = new TerminalPosition(clearStartX + start.getX() + clearWidth, (guiStartY + chestUISizeY - 1) + start.getY());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TerminalPosition guiStart = new TerminalPosition(renderMinX - RENDER_PADDING, renderMinY - RENDER_PADDING);
|
||||||
|
TerminalPosition guiEnd = new TerminalPosition(renderMaxX + RENDER_PADDING, renderMaxY + RENDER_PADDING);
|
||||||
|
|
||||||
if (!items.isEmpty()) {
|
if (!items.isEmpty()) {
|
||||||
drawUI(buffer, overrideBuffer, start, guiStartX, guiStartY);
|
drawUI(currentGrid, buffer, overrideBuffer, start, guiStartX, guiStartY);
|
||||||
}
|
}
|
||||||
|
|
||||||
RerenderUtils.rerenderPart(
|
RerenderUtils.rerenderPart(
|
||||||
@@ -156,16 +174,11 @@ public final class Chest extends GameObject implements UIClickHandler {
|
|||||||
|
|
||||||
RerenderScreen.ScreenPart sp = new RerenderScreen.ScreenPart(guiStart, guiEnd);
|
RerenderScreen.ScreenPart sp = new RerenderScreen.ScreenPart(guiStart, guiEnd);
|
||||||
|
|
||||||
|
if (!items.isEmpty()) {
|
||||||
listenerHashCode = uiClickHandlerRepository.registerCurrentRoomHandler(sp, this);
|
listenerHashCode = uiClickHandlerRepository.registerCurrentRoomHandler(sp, this);
|
||||||
|
|
||||||
//eventManager.emitEvent(RerenderScreen.full(terminalState.getTerminalScreen().getTerminalSize()));
|
|
||||||
|
|
||||||
eventManager.emitEvent(new RerenderScreen(sp));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calculateUISize(int itemCount) {
|
eventManager.emitEvent(new RerenderScreen(sp));
|
||||||
chestUISizeY = 20;
|
|
||||||
chestUISizeX = 4 + itemCount * 16 + (itemCount - 1) * 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearPreviousUI(
|
private void clearPreviousUI(
|
||||||
@@ -177,14 +190,11 @@ public final class Chest extends GameObject implements UIClickHandler {
|
|||||||
Pixel[][] overrideBuffer,
|
Pixel[][] overrideBuffer,
|
||||||
RoomCords start,
|
RoomCords start,
|
||||||
int guiStartY,
|
int guiStartY,
|
||||||
int chestUIStartX,
|
int clearStartX,
|
||||||
int chestTextureWidth,
|
int clearWidth,
|
||||||
int itemCount
|
int clearHeight
|
||||||
) {
|
) {
|
||||||
int clearWidth = 4 + (itemCount + 1) * 16 + itemCount * 2;
|
for (int y = guiStartY; y < guiStartY + clearHeight; y++) {
|
||||||
int clearStartX = chestUIStartX + (chestTextureWidth / 2) - (clearWidth / 2);
|
|
||||||
|
|
||||||
for (int y = guiStartY; y < guiStartY + chestUISizeY; y++) {
|
|
||||||
for (int x = clearStartX; x < clearStartX + clearWidth; x++) {
|
for (int x = clearStartX; x < clearStartX + clearWidth; x++) {
|
||||||
int pixel = RerenderUtils.getPixel(
|
int pixel = RerenderUtils.getPixel(
|
||||||
room,
|
room,
|
||||||
@@ -205,20 +215,33 @@ public final class Chest extends GameObject implements UIClickHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void drawUI(
|
private void drawUI(
|
||||||
|
Grid grid,
|
||||||
Pixel[][] buffer,
|
Pixel[][] buffer,
|
||||||
Pixel[][] overrideBuffer,
|
Pixel[][] overrideBuffer,
|
||||||
RoomCords start,
|
RoomCords start,
|
||||||
int guiStartX,
|
int guiStartX,
|
||||||
int guiStartY
|
int guiStartY
|
||||||
) {
|
) {
|
||||||
for (int y = 0; y < chestUISizeY; y++) {
|
BufferedImage[] textures = items.stream()
|
||||||
for (int x = 0; x < chestUISizeX; x++) {
|
.map(GameItem::getTexture)
|
||||||
Pixel pixel = getPixel(x, y, chestUISizeX, chestUISizeY);
|
.toArray(BufferedImage[]::new);
|
||||||
buffer[guiStartY + y + start.getY()][guiStartX + x + start.getX()] = pixel;
|
|
||||||
|
Pixel[][] uiPixels = grid.render(textures);
|
||||||
|
|
||||||
|
for (int y = 0; y < grid.getHeight(); y++) {
|
||||||
|
for (int x = 0; x < grid.getWidth(); x++) {
|
||||||
|
Pixel pixel = uiPixels[y][x];
|
||||||
|
|
||||||
|
int targetY = guiStartY + y + start.getY();
|
||||||
|
int targetX = guiStartX + x + start.getX();
|
||||||
|
|
||||||
|
if (targetY >= 0 && targetY < buffer.length && targetX >= 0 && targetX < buffer[0].length) {
|
||||||
|
buffer[targetY][targetX] = pixel;
|
||||||
overrideBuffer[guiStartY + y][guiStartX + x] = pixel;
|
overrideBuffer[guiStartY + y][guiStartX + x] = pixel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Pixel pixelToColored(int argb) {
|
private Pixel pixelToColored(int argb) {
|
||||||
int r = (argb >> 16) & 0xff;
|
int r = (argb >> 16) & 0xff;
|
||||||
@@ -227,65 +250,23 @@ public final class Chest extends GameObject implements UIClickHandler {
|
|||||||
return new ColoredPixel(new TextColor.RGB(r, g, b));
|
return new ColoredPixel(new TextColor.RGB(r, g, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Pixel getPixel(int objectX, int objectY, int width, int height) {
|
|
||||||
if (isBorder(objectX, objectY, width, height)) {
|
|
||||||
return new ColoredPixel(BORDER_COLOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
int screenX = objectX - 2;
|
|
||||||
int screenY = objectY - 2;
|
|
||||||
|
|
||||||
int part = screenX / 18;
|
|
||||||
int rest = screenX % 18;
|
|
||||||
|
|
||||||
if (rest >= 16) {
|
|
||||||
return new ColoredPixel(BORDER_COLOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
GameItem item = items.get(part);
|
|
||||||
BufferedImage texture = item.getTexture();
|
|
||||||
|
|
||||||
int pixel = texture.getRGB(rest, screenY);
|
|
||||||
int alpha = (pixel >> 24) & 0xff;
|
|
||||||
|
|
||||||
if (alpha == 0) {
|
|
||||||
return new ColoredPixel(TRANSPARENT_COLOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pixelToColored(pixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isBorder(int x, int y, int width, int height) {
|
|
||||||
return x <= 1 || x >= width - 2 || y <= 1 || y >= height - 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleClick(MouseAction mouseAction) {
|
public void handleClick(MouseAction mouseAction) {
|
||||||
int mouseX = mouseAction.getPosition().getColumn();
|
int mouseX = mouseAction.getPosition().getColumn();
|
||||||
int mouseY = mouseAction.getPosition().getRow();
|
int mouseY = mouseAction.getPosition().getRow();
|
||||||
|
|
||||||
log.debug("Mouse: x: {}, y: {}", mouseX, mouseY);
|
int localX = mouseX - actualDisplayStartX;
|
||||||
|
int localY = (mouseY * 2) - actualDisplayStartY;
|
||||||
|
|
||||||
int screenX = mouseX - actualDisplayStartX;
|
Grid grid = createGrid(items.size());
|
||||||
int screenY = (mouseY * 2) - actualDisplayStartY;
|
|
||||||
|
|
||||||
log.debug("Screen: x: {}, y: {}", screenX, screenY);
|
int itemIndex = grid.getItemIndexAt(localX, localY);
|
||||||
|
|
||||||
if (screenX < 0 || screenY < 0 || screenX > chestUISizeX || screenY > chestUISizeY) {
|
if (itemIndex == -1 || itemIndex >= items.size()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int part = screenX / 18;
|
GameItem item = items.get(itemIndex);
|
||||||
if (part >= items.size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rest = screenX % 18;
|
|
||||||
if (rest >= 16) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var item = items.get(part);
|
|
||||||
gameState.getPlayer().getInventory().add(item);
|
gameState.getPlayer().getInventory().add(item);
|
||||||
items.remove(item);
|
items.remove(item);
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,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 MainRoom(dependencyManager, resourceManager);
|
GameRoom mainRoom = new MainRoom(dependencyManager, resourceManager);
|
||||||
GameRoom rightRoom = new GameRoom(ResourceManager.Resource.ROOM2);
|
GameRoom rightRoom = new GameRoom(ResourceManager.Resource.ROOM2);
|
||||||
|
|||||||
@@ -28,6 +28,6 @@ public class MainRoom extends GameRoom {
|
|||||||
addObject(chest);
|
addObject(chest);
|
||||||
|
|
||||||
Zombie zombie = new Zombie(resourceManager, new RoomCords(100, 100));
|
Zombie zombie = new Zombie(resourceManager, new RoomCords(100, 100));
|
||||||
addMob(zombie);
|
//addMob(zombie);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
157
src/main/java/cz/jzitnik/ui/Grid.java
Normal file
157
src/main/java/cz/jzitnik/ui/Grid.java
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
package cz.jzitnik.ui;
|
||||||
|
|
||||||
|
import cz.jzitnik.ui.pixels.ColoredPixel;
|
||||||
|
import cz.jzitnik.ui.pixels.Pixel;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
public class Grid {
|
||||||
|
private final int itemsX;
|
||||||
|
private final int itemsY;
|
||||||
|
private final int outerBorderWidth;
|
||||||
|
private final int innerBorderWidth;
|
||||||
|
private final int itemPadding;
|
||||||
|
|
||||||
|
private final Pixel borderColor;
|
||||||
|
private final Pixel backgroundColor;
|
||||||
|
|
||||||
|
private final int itemSlotSize;
|
||||||
|
private final int cellSize;
|
||||||
|
private final int gridWidth;
|
||||||
|
private final int gridHeight;
|
||||||
|
|
||||||
|
public Grid(
|
||||||
|
int itemsX,
|
||||||
|
int itemsY,
|
||||||
|
int outerBorderWidth,
|
||||||
|
int innerBorderWidth,
|
||||||
|
int itemSize,
|
||||||
|
int itemPadding,
|
||||||
|
Pixel borderColor,
|
||||||
|
Pixel backgroundColor
|
||||||
|
) {
|
||||||
|
this.itemsX = itemsX;
|
||||||
|
this.itemsY = itemsY;
|
||||||
|
this.outerBorderWidth = outerBorderWidth;
|
||||||
|
this.innerBorderWidth = innerBorderWidth;
|
||||||
|
this.itemPadding = itemPadding;
|
||||||
|
this.borderColor = borderColor;
|
||||||
|
this.backgroundColor = backgroundColor;
|
||||||
|
|
||||||
|
this.itemSlotSize = itemSize + itemPadding * 2;
|
||||||
|
this.cellSize = itemSlotSize + innerBorderWidth;
|
||||||
|
|
||||||
|
this.gridWidth =
|
||||||
|
outerBorderWidth * 2 +
|
||||||
|
(itemsX * (itemSlotSize + innerBorderWidth) - innerBorderWidth);
|
||||||
|
|
||||||
|
this.gridHeight =
|
||||||
|
outerBorderWidth * 2 +
|
||||||
|
(itemsY * (itemSlotSize + innerBorderWidth) - innerBorderWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pixel[][] render(BufferedImage[] textures) {
|
||||||
|
Pixel[][] buffer = new Pixel[gridHeight][gridWidth];
|
||||||
|
|
||||||
|
// Background + borders
|
||||||
|
for (int y = 0; y < gridHeight; y++) {
|
||||||
|
for (int x = 0; x < gridWidth; x++) {
|
||||||
|
|
||||||
|
boolean isOuterBorder =
|
||||||
|
x < outerBorderWidth ||
|
||||||
|
y < outerBorderWidth ||
|
||||||
|
x >= gridWidth - outerBorderWidth ||
|
||||||
|
y >= gridHeight - outerBorderWidth;
|
||||||
|
|
||||||
|
boolean isInnerBorderX =
|
||||||
|
x >= outerBorderWidth + itemSlotSize &&
|
||||||
|
((x - outerBorderWidth - itemSlotSize) % cellSize) < innerBorderWidth;
|
||||||
|
|
||||||
|
boolean isInnerBorderY =
|
||||||
|
y >= outerBorderWidth + itemSlotSize &&
|
||||||
|
((y - outerBorderWidth - itemSlotSize) % cellSize) < innerBorderWidth;
|
||||||
|
|
||||||
|
buffer[y][x] = (isOuterBorder || isInnerBorderX || isInnerBorderY)
|
||||||
|
? borderColor
|
||||||
|
: backgroundColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Items
|
||||||
|
int maxItems = Math.min(textures.length, itemsX * itemsY);
|
||||||
|
|
||||||
|
for (int index = 0; index < maxItems; index++) {
|
||||||
|
BufferedImage texture = textures[index];
|
||||||
|
if (texture == null) continue;
|
||||||
|
|
||||||
|
int itemX = index % itemsX;
|
||||||
|
int itemY = index / itemsX;
|
||||||
|
|
||||||
|
int baseX =
|
||||||
|
outerBorderWidth +
|
||||||
|
itemX * cellSize +
|
||||||
|
itemPadding;
|
||||||
|
|
||||||
|
int baseY =
|
||||||
|
outerBorderWidth +
|
||||||
|
itemY * cellSize +
|
||||||
|
itemPadding;
|
||||||
|
|
||||||
|
for (int y = 0; y < texture.getHeight(); y++) {
|
||||||
|
for (int x = 0; x < texture.getWidth(); x++) {
|
||||||
|
int pixel = texture.getRGB(x, y);
|
||||||
|
int alpha = (pixel >> 24) & 0xff;
|
||||||
|
|
||||||
|
if (alpha == 0) continue;
|
||||||
|
|
||||||
|
int r = (pixel >> 16) & 0xff;
|
||||||
|
int g = (pixel >> 8) & 0xff;
|
||||||
|
int b = pixel & 0xff;
|
||||||
|
|
||||||
|
buffer[baseY + y][baseX + x] =
|
||||||
|
new ColoredPixel(new com.googlecode.lanterna.TextColor.RGB(r, g, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates which item index corresponds to the given x/y coordinates relative to the Grid's top-left.
|
||||||
|
* @param x X coordinate relative to the Grid (0 is left edge of the outer border)
|
||||||
|
* @param y Y coordinate relative to the Grid (0 is top edge of the outer border)
|
||||||
|
* @return The index of the item, or -1 if the click was on a border/background/out of bounds.
|
||||||
|
*/
|
||||||
|
public int getItemIndexAt(int x, int y) {
|
||||||
|
if (x < 0 || x >= gridWidth || y < 0 || y >= gridHeight) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x < outerBorderWidth || x >= gridWidth - outerBorderWidth ||
|
||||||
|
y < outerBorderWidth || y >= gridHeight - outerBorderWidth) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int contentX = x - outerBorderWidth;
|
||||||
|
int contentY = y - outerBorderWidth;
|
||||||
|
|
||||||
|
int col = contentX / cellSize;
|
||||||
|
int row = contentY / cellSize;
|
||||||
|
|
||||||
|
if (contentX % cellSize >= itemSlotSize) return -1;
|
||||||
|
if (contentY % cellSize >= itemSlotSize) return -1;
|
||||||
|
|
||||||
|
if (col >= itemsX || row >= itemsY) return -1;
|
||||||
|
|
||||||
|
return row * itemsX + col;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
return gridWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight() {
|
||||||
|
return gridHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user