feat: Render stamina

This commit is contained in:
2026-01-02 22:37:54 +01:00
parent 27cdde97a0
commit 4136696c83
11 changed files with 150 additions and 33 deletions

View File

@@ -0,0 +1,6 @@
package cz.jzitnik.events;
import cz.jzitnik.utils.events.Event;
public class RenderStats implements Event {
}

View File

@@ -19,6 +19,7 @@ import cz.jzitnik.states.RenderState;
import cz.jzitnik.states.ScreenBuffer;
import cz.jzitnik.states.TerminalState;
import cz.jzitnik.ui.Inventory;
import cz.jzitnik.ui.Stats;
import cz.jzitnik.utils.DependencyManager;
import cz.jzitnik.utils.RerenderUtils;
import cz.jzitnik.utils.UIClickHandlerRepository;
@@ -58,6 +59,8 @@ public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
private UIClickHandlerRepository uiClickHandlerRepository;
@InjectDependency
private Inventory inventory;
@InjectDependency
private Stats stats;
public FullRoomDrawHandler(DependencyManager dm) {
super(dm);
@@ -86,6 +89,7 @@ public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
RerenderUtils.rerenderPart(0, width - 1, 0, height - 1, startX, startY, currentRoom, room, player, playerTexture, screenBuffer, resourceManager, debugging);
if (event.isFullRerender()) {
inventory.renderInventoryRerender();
stats.rerender();
uiClickHandlerRepository.registerGlobalHandler(inventory);
}

View File

@@ -21,6 +21,7 @@ import cz.jzitnik.states.RenderState;
import cz.jzitnik.states.ScreenBuffer;
import cz.jzitnik.states.PlayerMovementState;
import cz.jzitnik.states.TerminalState;
import cz.jzitnik.ui.Stats;
import cz.jzitnik.utils.DependencyManager;
import cz.jzitnik.utils.RerenderUtils;
import cz.jzitnik.utils.events.AbstractEventHandler;
@@ -52,6 +53,8 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
private Logging logging;
@InjectState
private PlayerMovementState playerMovementState;
@InjectDependency
private Stats stats;
public PlayerMoveEventHandler(DependencyManager dm) {
super(dm);
@@ -126,7 +129,8 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
}
playerMovementState.setLastMovement(System.currentTimeMillis());
if (isSprinting) {
int newStamina = player.decreaseStamina();
player.decreaseStamina();
stats.rerender();
}
int newPlayerX = playerCords.getX();
@@ -148,10 +152,16 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
RerenderUtils.rerenderPart(forStartX, forEndX, forStartY, forEndY, startX, startY, currentRoom, room, player, playerTexture, screenBuffer, resourceManager, debugging);
eventManager.emitEvent(new RerenderScreen(
new RerenderScreen.ScreenPart(
new TerminalPosition(forStartX + startX, forStartY + startY),
new TerminalPosition(forEndX + 1 + startX, forEndY + startY)
)
new RerenderScreen.ScreenPart[]{
new RerenderScreen.ScreenPart(
new TerminalPosition(forStartX + startX, forStartY + startY),
new TerminalPosition(forEndX + 1 + startX, forEndY + startY)
),
new RerenderScreen.ScreenPart(
new TerminalPosition(Stats.OFFSET_X, Stats.OFFSET_X),
new TerminalPosition(Stats.OFFSET_X + Stats.WIDTH, Stats.OFFSET_Y + Stats.HEIGHT)
)
}
));
}

View File

@@ -0,0 +1,33 @@
package cz.jzitnik.events.handlers;
import com.googlecode.lanterna.TerminalPosition;
import cz.jzitnik.annotations.EventHandler;
import cz.jzitnik.annotations.injectors.InjectDependency;
import cz.jzitnik.events.RenderStats;
import cz.jzitnik.events.RerenderScreen;
import cz.jzitnik.ui.Stats;
import cz.jzitnik.utils.DependencyManager;
import cz.jzitnik.utils.events.AbstractEventHandler;
import cz.jzitnik.utils.events.EventManager;
@EventHandler(RenderStats.class)
public class RenderStatsHandler extends AbstractEventHandler<RenderStats> {
@InjectDependency
private EventManager eventManager;
@InjectDependency
private Stats stats;
public RenderStatsHandler(DependencyManager dm) {
super(dm);
}
@Override
public void handle(RenderStats event) {
stats.rerender();
eventManager.emitEvent(new RerenderScreen(new RerenderScreen.ScreenPart(
new TerminalPosition(Stats.OFFSET_X, Stats.OFFSET_X),
new TerminalPosition(Stats.OFFSET_X + Stats.WIDTH, Stats.OFFSET_Y + Stats.HEIGHT)
)));
}
}

View File

@@ -49,10 +49,10 @@ public class RoomChangeEventHandler extends AbstractEventHandler<RoomChangeEvent
}
switch (event.door()) {
case LEFT -> playerCords.updateCords(155, 60);
case RIGHT -> playerCords.updateCords(30, 50);
case TOP -> playerCords.updateCords(90, 110);
case BOTTOM -> playerCords.updateCords(90, 10);
case LEFT -> playerCords.updateCords(155, playerCords.getY());
case RIGHT -> playerCords.updateCords(30, playerCords.getY());
case TOP -> playerCords.updateCords(playerCords.getX(), 110);
case BOTTOM -> playerCords.updateCords(playerCords.getX(), 10);
}
gameState.setCurrentRoom(newRoom);

View File

@@ -27,13 +27,11 @@ public class Player {
private GameItem selectedItem;
private boolean swinging = false;
public int increaseStamina() {
log.debug("Stamina: {}", stamina + 1);
return ++stamina;
public void increaseStamina() {
stamina++;
}
public int decreaseStamina() {
log.debug("Stamina: {}", stamina - 1);
return --stamina;
public void decreaseStamina() {
stamina--;
}
public int getDamageDeal() {

View File

@@ -250,7 +250,7 @@ public final class Chest extends GameObject implements UIClickHandler {
}
@Override
public void handleClick(MouseAction mouseAction) {
public boolean handleClick(MouseAction mouseAction) {
int mouseX = mouseAction.getPosition().getColumn();
int mouseY = mouseAction.getPosition().getRow();
@@ -262,21 +262,23 @@ public final class Chest extends GameObject implements UIClickHandler {
int itemIndex = grid.getItemIndexAt(localX, localY);
if (itemIndex == -1 || itemIndex >= items.size()) {
return;
return false;
}
GameItem item = items.get(itemIndex);
boolean added = gameState.getPlayer().addItem(item);
if (!added) {
return;
return true;
}
eventManager.emitEvent(new InventoryRerender());
items.remove(item);
if (items.isEmpty()) {
uiClickHandlerRepository.removeHandlerForCurrentRoom(listenerHashCode, this);
uiClickHandlerRepository.removeHandlerForCurrentRoom(listenerHashCode);
}
render(true);
return true;
}
}

View File

@@ -3,8 +3,12 @@ package cz.jzitnik.game.objects;
import cz.jzitnik.events.MouseAction;
public interface UIClickHandler {
void handleClick(MouseAction mouseAction);
boolean handleClick(MouseAction mouseAction);
default void handleMove(MouseAction ignoredMouseAction) {}
default void handleElse(MouseAction ignoredMouseAction) {}
default boolean handleMove(MouseAction ignoredMouseAction) {
return false;
}
default boolean handleElse(MouseAction ignoredMouseAction) {
return false;
}
}

View File

@@ -5,11 +5,13 @@ import cz.jzitnik.annotations.injectors.InjectConfig;
import cz.jzitnik.annotations.injectors.InjectDependency;
import cz.jzitnik.annotations.injectors.InjectState;
import cz.jzitnik.config.PlayerConfig;
import cz.jzitnik.events.RenderStats;
import cz.jzitnik.game.GameState;
import cz.jzitnik.game.Player;
import cz.jzitnik.states.PlayerMovementState;
import cz.jzitnik.utils.DependencyManager;
import cz.jzitnik.utils.ScheduledTaskManager;
import cz.jzitnik.utils.events.EventManager;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@@ -55,6 +57,9 @@ public class StaminaIncreaseTask implements Runnable {
@InjectConfig
private PlayerConfig playerConfig;
@InjectDependency
private EventManager eventManager;
@Override
public void run() {
long nowTime = System.currentTimeMillis();
@@ -68,6 +73,7 @@ public class StaminaIncreaseTask implements Runnable {
}
player.increaseStamina();
eventManager.emitEvent(new RenderStats());
}
}
}

View File

@@ -0,0 +1,51 @@
package cz.jzitnik.ui;
import com.googlecode.lanterna.TextColor;
import cz.jzitnik.annotations.Dependency;
import cz.jzitnik.annotations.injectors.InjectState;
import cz.jzitnik.game.GameState;
import cz.jzitnik.game.Player;
import cz.jzitnik.states.ScreenBuffer;
import cz.jzitnik.ui.pixels.ColoredPixel;
import cz.jzitnik.ui.pixels.Empty;
import cz.jzitnik.ui.pixels.Pixel;
import lombok.Getter;
@Getter
@Dependency
public class Stats {
public static final int BARS_COUNT = 1;
public static final int BAR_WIDTH = 72;
public static final int BAR_HEIGHT = 8;
public static final int BAR_PADDING = 2;
public static final int HEIGHT = BAR_HEIGHT * BARS_COUNT + (BAR_PADDING * (BARS_COUNT - 1));
public static final int WIDTH = BAR_WIDTH;
public static final int OFFSET_X = 5;
public static final int OFFSET_Y = 5;
private static final Pixel STAMINA_COLOR = new ColoredPixel(new TextColor.RGB(207, 175, 89));
@InjectState
private GameState gameState;
@InjectState
private ScreenBuffer screenBuffer;
public void rerender() {
var buffer = screenBuffer.getRenderedBuffer();
float staminaDelta = (float) gameState.getPlayer().getStamina() / Player.MAX_STAMINA;
float staminaAmount = (BAR_WIDTH - 2) * staminaDelta;
for (int x = 0; x < BAR_WIDTH; x++) {
for (int y = 0; y < BAR_HEIGHT; y++) {
if (x == 0 || y == 0 || x == BAR_WIDTH - 1 || y == BAR_HEIGHT - 1 || x - 1 < staminaAmount) {
buffer[y + OFFSET_Y][x + OFFSET_X] = STAMINA_COLOR;
} else {
buffer[y + OFFSET_Y][x + OFFSET_X] = new Empty();
}
}
}
}
}

View File

@@ -48,15 +48,16 @@ public class UIClickHandlerRepository {
public boolean handleClick(MouseAction mouseAction) {
if (roomSpecificHandlers.containsKey(gameState.getCurrentRoom())) {
Map<RerenderScreen.ScreenPart, UIClickHandler> handlers = roomSpecificHandlers.get(gameState.getCurrentRoom());
TerminalPosition position = new TerminalPosition(mouseAction.getPosition().getColumn(), mouseAction.getPosition().getRow() * 2);
for (var entry : handlers.entrySet()) {
RerenderScreen.ScreenPart part = entry.getKey();
UIClickHandler uiClickHandler = entry.getValue();
TerminalPosition position = new TerminalPosition(mouseAction.getPosition().getColumn(), mouseAction.getPosition().getRow() * 2);
if (part.isWithin(position)) {
uiClickHandler.handleClick(mouseAction);
return true;
if (uiClickHandler.handleClick(mouseAction)) {
return true;
}
}
}
}
@@ -73,15 +74,16 @@ public class UIClickHandlerRepository {
public boolean handleElse(MouseAction mouseAction) {
if (roomSpecificHandlers.containsKey(gameState.getCurrentRoom())) {
Map<RerenderScreen.ScreenPart, UIClickHandler> handlers = roomSpecificHandlers.get(gameState.getCurrentRoom());
TerminalPosition position = new TerminalPosition(mouseAction.getPosition().getColumn(), mouseAction.getPosition().getRow() * 2);
for (var entry : handlers.entrySet()) {
RerenderScreen.ScreenPart part = entry.getKey();
UIClickHandler uiClickHandler = entry.getValue();
TerminalPosition position = new TerminalPosition(mouseAction.getPosition().getColumn(), mouseAction.getPosition().getRow() * 2);
if (part.isWithin(position)) {
uiClickHandler.handleElse(mouseAction);
return true;
if (uiClickHandler.handleElse(mouseAction)) {
return true;
}
}
}
}
@@ -98,14 +100,15 @@ public class UIClickHandlerRepository {
public boolean handleMove(MouseAction mouseAction) {
if (roomSpecificHandlers.containsKey(gameState.getCurrentRoom())) {
Map<RerenderScreen.ScreenPart, UIClickHandler> handlers = roomSpecificHandlers.get(gameState.getCurrentRoom());
TerminalPosition position = new TerminalPosition(mouseAction.getPosition().getColumn(), mouseAction.getPosition().getRow() * 2);
for (var entry : handlers.entrySet()) {
RerenderScreen.ScreenPart part = entry.getKey();
UIClickHandler uiClickHandler = entry.getValue();
TerminalPosition position = new TerminalPosition(mouseAction.getPosition().getColumn(), mouseAction.getPosition().getRow() * 2);
if (part.isWithin(position)) {
uiClickHandler.handleMove(mouseAction);
return true;
if (uiClickHandler.handleMove(mouseAction)) {
return true;
}
}
}
}
@@ -119,14 +122,14 @@ public class UIClickHandlerRepository {
return false;
}
public void removeHandlerForCurrentRoom(int screenPartHashCode, UIClickHandler uiClickHandler) {
public void removeHandlerForCurrentRoom(int screenPartHashCode) {
GameRoom currentRoom = gameState.getCurrentRoom();
if (!roomSpecificHandlers.containsKey(currentRoom)) return;
Map<RerenderScreen.ScreenPart, UIClickHandler> handlers = roomSpecificHandlers.get(currentRoom);
for (var key : handlers.keySet()) {
if (key.hashCode() == screenPartHashCode) {
handlers.remove(key, uiClickHandler);
handlers.remove(key);
}
}
}