From 10b81d018cbfc26dd2c635b538f20a8a1f1f0676 Mon Sep 17 00:00:00 2001 From: jzitnik-dev Date: Thu, 3 Apr 2025 08:21:39 +0200 Subject: [PATCH] refactor(ui): Moved logic of Menu --- src/main/java/cz/jzitnik/game/ui/Escape.java | 183 ++++--------------- src/main/java/cz/jzitnik/game/ui/Menu.java | 120 ++++++++++++ 2 files changed, 155 insertions(+), 148 deletions(-) create mode 100644 src/main/java/cz/jzitnik/game/ui/Menu.java diff --git a/src/main/java/cz/jzitnik/game/ui/Escape.java b/src/main/java/cz/jzitnik/game/ui/Escape.java index 024122d..ae43160 100644 --- a/src/main/java/cz/jzitnik/game/ui/Escape.java +++ b/src/main/java/cz/jzitnik/game/ui/Escape.java @@ -2,9 +2,7 @@ package cz.jzitnik.game.ui; import org.jline.terminal.MouseEvent; import org.jline.terminal.Terminal; - import cz.jzitnik.game.Game; -import cz.jzitnik.game.sprites.ui.Font; import cz.jzitnik.game.sprites.ui.Font.*; import cz.jzitnik.tui.ScreenRenderer; import lombok.extern.slf4j.Slf4j; @@ -12,16 +10,44 @@ import lombok.extern.slf4j.Slf4j; @Slf4j public class Escape { private Game game; - private int btnWidth; - private int leftPad; - private int mainTextHeight; - private int buttonHeight; - private int textButtonMargin; - - private boolean[] buttonsHover = { false, false, false }; + private Menu menu; public Escape(Game game) { this.game = game; + this.menu = new Menu(game, "2DCraft", new String[] { "Continue", "Options", "Save and exit" }, + this::onButtonClick); + } + + public void reset() { + menu.reset(); + } + + public void render(StringBuilder buffer, Terminal terminal) { + menu.render(buffer, terminal); + } + + public void mouse(MouseEvent mouseEvent, Terminal terminal, ScreenRenderer screenRenderer) { + menu.handleMouse(mouseEvent, terminal, screenRenderer); + } + + private void onButtonClick(int index, ScreenRenderer screenRenderer) { + switch (index) { + case 0: + game.setWindow(Window.WORLD); + break; + case 1: + // Options logic placeholder + break; + case 2: + game.setWindow(Window.SAVE_EXIT); + screenRenderer.render(game); + game.getGameStates().dependencies.gameSaver.save(game); + game.setWindow(Window.SAVED); + screenRenderer.render(game); + System.exit(0); + break; + } + screenRenderer.render(game); } public void renderSave(StringBuilder buffer, Terminal terminal) { @@ -43,143 +69,4 @@ public class Escape { buffer.append("\n".repeat(top)); buffer.append(savingText.getData()); } - - public void render(StringBuilder buffer, Terminal terminal) { - var font = game.getGameStates().dependencies.font; - var width = terminal.getWidth(); - var height = terminal.getHeight(); - - log.debug("Terminal width: {}", width); - log.debug("Terminal height: {}", height); - - var twodcraft = font.line(terminal, "2DCraft", Size.LARGE, Align.CENTER); - buffer.append(twodcraft.getData()); - mainTextHeight = twodcraft.getHeight(); - - if (height < 600) { - textButtonMargin = 15; - } else if (height < 800) { - textButtonMargin = 30; - } else { - textButtonMargin = 50; - } - - buffer.append("\n".repeat(textButtonMargin)); - - renderButton(buffer, "Continue", width, font, terminal, buttonsHover[0]); - buffer.append("\n".repeat(textButtonMargin / 2)); - renderButton(buffer, "Options", width, font, terminal, buttonsHover[1]); - buffer.append("\n".repeat(textButtonMargin / 2)); - renderButton(buffer, "Save and exit", width, font, terminal, buttonsHover[2]); - } - - public void mouse(MouseEvent mouseEvent, Terminal terminal, ScreenRenderer screenRenderer) { - int x = mouseEvent.getX(); - int y = mouseEvent.getY(); - var type = mouseEvent.getType(); - - int buttonx = x - leftPad; - int buttony = y - (mainTextHeight + textButtonMargin); - int margin = textButtonMargin / 2; - - boolean changed = false; - - if (buttonx > 0 && buttonx <= btnWidth) { - // Continue - if (buttony > 0 && buttony < buttonHeight) { - if (type == MouseEvent.Type.Pressed) { - game.setWindow(Window.WORLD); - screenRenderer.render(game); - return; - } - - if (buttonsHover[0] == false) { - buttonsHover[0] = true; - changed = true; - } - } else if (buttonsHover[0]) { - buttonsHover[0] = false; - changed = true; - } - - // Options - if (buttony > buttonHeight + margin && buttony < 2 * buttonHeight + margin) { - if (type == MouseEvent.Type.Pressed) { - return; - } - - if (buttonsHover[1] == false) { - buttonsHover[1] = true; - changed = true; - } - } else if (buttonsHover[1]) { - buttonsHover[1] = false; - changed = true; - } - - // Save and exit - if (buttony > 2 * (buttonHeight + margin) && buttony < buttonHeight + 2 * (buttonHeight + margin)) { - if (type == MouseEvent.Type.Pressed) { - game.setWindow(Window.SAVE_EXIT); - screenRenderer.render(game); - - // Save game - game.getGameStates().dependencies.gameSaver.save(game); - - game.setWindow(Window.SAVED); - screenRenderer.render(game); - - System.exit(0); - } - - if (buttonsHover[2] == false) { - buttonsHover[2] = true; - changed = true; - } - } else if (buttonsHover[2]) { - buttonsHover[2] = false; - changed = true; - } - } - - if (changed) { - screenRenderer.render(game); - } - } - - private void renderButton(StringBuilder buffer, String txt, int width, Font font, Terminal terminal, - boolean selected) { - int btnWidth = Math.min(350, (int) (width * (3.0 / 4))); - this.btnWidth = btnWidth; - int leftPad = (width - btnWidth) / 2; - this.leftPad = leftPad; - log.debug("Button width: {}px ", btnWidth); - - final String color = selected ? "[48;2;70;70;70m" : "[48;2;116;115;113m"; - - var text = font.line(terminal, txt, Size.SMALL, Align.CENTER, new Custom.Width(btnWidth - 4), - new Background(color)); - int btnHeight = text.getHeight() + 4; - this.buttonHeight = btnHeight; - var lines = text.getData().split("\n"); - - for (int y = 0; y < btnHeight; y++) { - buffer.append(" ".repeat(leftPad)); - if (y == 0 || y == 1 || y == btnHeight - 1 || y == btnHeight - 2) { - buffer.append("\033").append(color).append(" ".repeat(btnWidth)); - } else { - buffer.append("\033").append(color).append(" ".repeat(2)); - buffer.append(lines[y - 2]); - buffer.append("\033").append(color).append(" ".repeat(2)); - } - - buffer.append("\033[0m\n"); - } - } - - public void reset() { - for (int i = 0; i < buttonsHover.length; i++) { - buttonsHover[i] = false; - } - } } diff --git a/src/main/java/cz/jzitnik/game/ui/Menu.java b/src/main/java/cz/jzitnik/game/ui/Menu.java new file mode 100644 index 0000000..1b1d6bc --- /dev/null +++ b/src/main/java/cz/jzitnik/game/ui/Menu.java @@ -0,0 +1,120 @@ +package cz.jzitnik.game.ui; + +import org.jline.terminal.MouseEvent; +import org.jline.terminal.Terminal; + +import cz.jzitnik.game.Game; +import cz.jzitnik.game.sprites.ui.Font; +import cz.jzitnik.game.sprites.ui.Font.*; +import cz.jzitnik.tui.ScreenRenderer; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class Menu { + private Game game; + private String headingText; + private String[] buttonLabels; + private boolean[] buttonsHover; + private int btnWidth; + private int leftPad; + private int mainTextHeight; + private int buttonHeight; + private int textButtonMargin; + private ButtonClickHandler buttonClickHandler; + + public Menu(Game game, String headingText, String[] buttonLabels, ButtonClickHandler buttonClickHandler) { + this.game = game; + this.headingText = headingText; + this.buttonLabels = buttonLabels; + this.buttonsHover = new boolean[buttonLabels.length]; + this.buttonClickHandler = buttonClickHandler; + } + + public void render(StringBuilder buffer, Terminal terminal) { + var font = game.getGameStates().dependencies.font; + var width = terminal.getWidth(); + var height = terminal.getHeight(); + + var heading = font.line(terminal, headingText, Size.LARGE, Align.CENTER); + buffer.append(heading.getData()); + mainTextHeight = heading.getHeight(); + + textButtonMargin = (height < 600) ? 15 : (height < 800) ? 30 : 50; + buffer.append("\n".repeat(textButtonMargin)); + + for (int i = 0; i < buttonLabels.length; i++) { + renderButton(buffer, buttonLabels[i], width, font, terminal, buttonsHover[i]); + buffer.append("\n".repeat(textButtonMargin / 2)); + } + } + + public void handleMouse(MouseEvent mouseEvent, Terminal terminal, ScreenRenderer screenRenderer) { + int x = mouseEvent.getX(); + int y = mouseEvent.getY(); + var type = mouseEvent.getType(); + + int buttonx = x - leftPad; + int buttony = y - (mainTextHeight + textButtonMargin); + int margin = textButtonMargin / 2; + + boolean changed = false; + + if (buttonx > 0 && buttonx <= btnWidth) { + for (int i = 0; i < buttonLabels.length; i++) { + int top = i * (buttonHeight + margin); + int bottom = top + buttonHeight; + + if (buttony > top && buttony < bottom) { + if (type == MouseEvent.Type.Pressed) { + buttonClickHandler.onClick(i, screenRenderer); + return; + } + if (!buttonsHover[i]) { + buttonsHover[i] = true; + changed = true; + } + } else if (buttonsHover[i]) { + buttonsHover[i] = false; + changed = true; + } + } + } + + if (changed) { + screenRenderer.render(game); + } + } + + private void renderButton(StringBuilder buffer, String txt, int width, Font font, Terminal terminal, boolean selected) { + btnWidth = Math.min(350, (int) (width * (3.0 / 4))); + leftPad = (width - btnWidth) / 2; + log.debug("Button width: {}px ", btnWidth); + + final String color = selected ? "[48;2;70;70;70m" : "[48;2;116;115;113m"; + var text = font.line(terminal, txt, Size.SMALL, Align.CENTER, new Custom.Width(btnWidth - 4), new Background(color)); + buttonHeight = text.getHeight() + 4; + var lines = text.getData().split("\n"); + + for (int y = 0; y < buttonHeight; y++) { + buffer.append(" ".repeat(leftPad)); + if (y < 2 || y >= buttonHeight - 2) { + buffer.append("\033").append(color).append(" ".repeat(btnWidth)); + } else { + buffer.append("\033").append(color).append(" ".repeat(2)); + buffer.append(lines[y - 2]); + buffer.append("\033").append(color).append(" ".repeat(2)); + } + buffer.append("\033[0m\n"); + } + } + + interface ButtonClickHandler { + void onClick(int index, ScreenRenderer screenRenderer); + } + + public void reset() { + for (int i = 0; i < buttonsHover.length; i++) { + buttonsHover[i] = false; + } + } +}