forked from jzitnik/twodcraft
refactor(ui): Better API for UI texts
This commit is contained in:
parent
6ece6d3096
commit
6028b54d10
@ -9,6 +9,8 @@ import cz.jzitnik.game.handlers.tooluse.ToolUseProvider;
|
|||||||
import cz.jzitnik.game.mobs.EntityHurtAnimation;
|
import cz.jzitnik.game.mobs.EntityHurtAnimation;
|
||||||
import cz.jzitnik.game.mobs.EntityKill;
|
import cz.jzitnik.game.mobs.EntityKill;
|
||||||
import cz.jzitnik.game.smelting.Smelting;
|
import cz.jzitnik.game.smelting.Smelting;
|
||||||
|
import cz.jzitnik.game.sprites.ui.Font;
|
||||||
|
import cz.jzitnik.game.ui.Escape;
|
||||||
|
|
||||||
public class Dependencies {
|
public class Dependencies {
|
||||||
public PlaceHandler placeHandler = new PlaceHandler();
|
public PlaceHandler placeHandler = new PlaceHandler();
|
||||||
@ -20,4 +22,6 @@ public class Dependencies {
|
|||||||
public Smelting smelting = new Smelting();
|
public Smelting smelting = new Smelting();
|
||||||
public ToolUseProvider toolUseProvider = new ToolUseProvider();
|
public ToolUseProvider toolUseProvider = new ToolUseProvider();
|
||||||
public Sound sound = new Sound();
|
public Sound sound = new Sound();
|
||||||
|
public Font font = new Font();
|
||||||
|
public Escape escape = new Escape();
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,34 @@
|
|||||||
package cz.jzitnik.game.sprites.ui;
|
package cz.jzitnik.game.sprites.ui;
|
||||||
|
|
||||||
import cz.jzitnik.tui.ResourceLoader;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import org.jline.terminal.Terminal;
|
||||||
|
|
||||||
|
import cz.jzitnik.tui.ResourceLoader;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Font {
|
public class Font {
|
||||||
private final String[] lines = ResourceLoader.loadResource("ui/font.ans").split("\n");
|
private final String[] lines = ResourceLoader.loadResource("ui/font.ans").split("\n");
|
||||||
private final int HEIGHT = 7;
|
private final int HEIGHT = 7;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public class FontDTO {
|
||||||
|
private String data;
|
||||||
|
private int width;
|
||||||
|
private int height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
private class CharDTO {
|
||||||
|
private String character;
|
||||||
|
private int width;
|
||||||
|
}
|
||||||
|
|
||||||
private String get(int startY, int startX, int height, int width, String color) {
|
private String get(int startY, int startX, int height, int width, String color) {
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
|
||||||
@ -18,11 +41,10 @@ public class Font {
|
|||||||
stringBuilder.append("\033[0m\n");
|
stringBuilder.append("\033[0m\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return stringBuilder.toString();
|
return stringBuilder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getDigit(char digit, String color) {
|
private CharDTO getDigit(char digit, String color) {
|
||||||
int num = Integer.valueOf(digit);
|
int num = Integer.valueOf(digit);
|
||||||
int width = 12;
|
int width = 12;
|
||||||
int startY = HEIGHT;
|
int startY = HEIGHT;
|
||||||
@ -33,12 +55,12 @@ public class Font {
|
|||||||
startX = (26 + 9) * width;
|
startX = (26 + 9) * width;
|
||||||
}
|
}
|
||||||
|
|
||||||
return get(startY, startX, HEIGHT, width, color);
|
return new CharDTO(get(startY, startX, HEIGHT, width, color), width);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getChar(char character, String color) {
|
public CharDTO getChar(char character, String color) {
|
||||||
if (character == ' ') {
|
if (character == ' ') {
|
||||||
return ("\033[49m ".repeat(12) + "\n").repeat(HEIGHT);
|
return new CharDTO(("\033[49m ".repeat(12) + "\n").repeat(HEIGHT), 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Character.isDigit(character)) {
|
if (Character.isDigit(character)) {
|
||||||
@ -50,16 +72,19 @@ public class Font {
|
|||||||
int startY = (upper ? 0 : 1) * HEIGHT;
|
int startY = (upper ? 0 : 1) * HEIGHT;
|
||||||
int startX = (upper ? character - 'A' : character - 'a') * width;
|
int startX = (upper ? character - 'A' : character - 'a') * width;
|
||||||
|
|
||||||
return get(startY, startX, HEIGHT, width, color);
|
return new CharDTO(get(startY, startX, HEIGHT, width, color), width);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLine(String text) {
|
public FontDTO getLine(String text) {
|
||||||
char[] chars = text.toCharArray();
|
char[] chars = text.toCharArray();
|
||||||
|
|
||||||
String[][] letters = new String[chars.length][];
|
String[][] letters = new String[chars.length][];
|
||||||
|
int width = 0;
|
||||||
|
|
||||||
for (int i = 0; i < chars.length; i++) {
|
for (int i = 0; i < chars.length; i++) {
|
||||||
letters[i] = getChar(chars[i], "[47m").split("\n");
|
var charDto = getChar(chars[i], "[47m");
|
||||||
|
letters[i] = charDto.getCharacter().split("\n");
|
||||||
|
width += charDto.getWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
@ -72,6 +97,137 @@ public class Font {
|
|||||||
stringBuilder.append("\n");
|
stringBuilder.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return stringBuilder.toString();
|
return new FontDTO(stringBuilder.toString(), width, HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FontDTO scale(FontDTO font, int times) {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
var line = font.getData();
|
||||||
|
var lines = line.split("\n");
|
||||||
|
|
||||||
|
for (int lineNum = 0; lineNum < lines.length; lineNum++) {
|
||||||
|
for (int i = 0; i < times; i++) {
|
||||||
|
stringBuilder.append(scaleLine(lines[lineNum], times));
|
||||||
|
stringBuilder.append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FontDTO(stringBuilder.toString(), font.getWidth() * times, font.getHeight() * times);
|
||||||
|
}
|
||||||
|
|
||||||
|
private StringBuilder scaleLine(String line, int times) {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
|
||||||
|
for (char c : line.toCharArray()) {
|
||||||
|
if (c == ' ') {
|
||||||
|
result.append(" ".repeat(times));
|
||||||
|
} else {
|
||||||
|
result.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FontDTO getScaledLine(String text, Size size, int termWidth) {
|
||||||
|
return scale(getLine(text), size.getFunc().apply(termWidth));
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will probably need little more work
|
||||||
|
public enum Size {
|
||||||
|
SMALL((x) -> {
|
||||||
|
if (x < 800) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}),
|
||||||
|
MEDIUM((x) -> {
|
||||||
|
if (x < 800) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}),
|
||||||
|
LARGE((x) -> {
|
||||||
|
if (x < 800) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 4;
|
||||||
|
});
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private Function<Integer, Integer> func;
|
||||||
|
|
||||||
|
Size(Function<Integer, Integer> func) {
|
||||||
|
this.func = func;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Align {
|
||||||
|
LEFT,
|
||||||
|
RIGHT,
|
||||||
|
CENTER
|
||||||
|
}
|
||||||
|
|
||||||
|
private FontDTO applyAlignment(FontDTO data, Align alignment, int termWidth) {
|
||||||
|
return switch (alignment) {
|
||||||
|
case LEFT -> data;
|
||||||
|
case CENTER -> {
|
||||||
|
var lines = data.getData().split("\n");
|
||||||
|
int nowWidth = data.getWidth();
|
||||||
|
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
|
var leftPad = (termWidth - nowWidth) / 2;
|
||||||
|
|
||||||
|
for (int i = 0; i < lines.length; i++) {
|
||||||
|
buffer.append(" ".repeat(leftPad)).append(lines[i]);
|
||||||
|
buffer.append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
yield new FontDTO(buffer.toString(), termWidth, data.getHeight());
|
||||||
|
}
|
||||||
|
case RIGHT -> {
|
||||||
|
var lines = data.getData().split("\n");
|
||||||
|
int nowWidth = data.getWidth();
|
||||||
|
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
|
var leftPad = termWidth - nowWidth;
|
||||||
|
|
||||||
|
for (int i = 0; i < lines.length; i++) {
|
||||||
|
buffer.append(" ".repeat(leftPad)).append(lines[i]);
|
||||||
|
buffer.append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
yield new FontDTO(buffer.toString(), termWidth, data.getHeight());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public FontDTO line(Terminal terminal, String text, Object... attributes) {
|
||||||
|
int termWidth = terminal.getWidth();
|
||||||
|
//int termHeight = terminal.getHeight();
|
||||||
|
|
||||||
|
Size fontSize = Size.MEDIUM;
|
||||||
|
Align alignment = Align.LEFT;
|
||||||
|
|
||||||
|
for (Object attribute : attributes) {
|
||||||
|
if (Size.class.isAssignableFrom(attribute.getClass())) {
|
||||||
|
fontSize = (Size) attribute;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Align.class.isAssignableFrom(attribute.getClass())) {
|
||||||
|
alignment = (Align) attribute;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.error("Invalid attribute class {}. Skipping", attribute.getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return applyAlignment(getScaledLine(text, fontSize, termWidth), alignment, termWidth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,21 @@ package cz.jzitnik.game.ui;
|
|||||||
|
|
||||||
import org.jline.terminal.Terminal;
|
import org.jline.terminal.Terminal;
|
||||||
|
|
||||||
import cz.jzitnik.game.sprites.ui.Font;
|
import cz.jzitnik.game.Game;
|
||||||
|
import cz.jzitnik.game.sprites.ui.Font.*;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Escape {
|
public class Escape {
|
||||||
public static void render(StringBuilder buffer, Terminal terminal) {
|
public void render(StringBuilder buffer, Terminal terminal, Game game) {
|
||||||
Font font = new Font();
|
var font = game.getGameStates().dependencies.font;
|
||||||
String character = font.getLine("Never gonna give you up never gonna let you down");
|
var width = terminal.getWidth();
|
||||||
|
var height = terminal.getHeight();
|
||||||
|
|
||||||
buffer.append(character);
|
log.debug("Terminal width: {}", width);
|
||||||
|
log.debug("Terminal height: {}", height);
|
||||||
|
|
||||||
|
var twodcraft = font.line(terminal, "2DCraft", Size.LARGE, Align.LEFT);
|
||||||
|
buffer.append(twodcraft.getData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,7 @@ public class ScreenRenderer {
|
|||||||
main.append("\033[H\033[2J");
|
main.append("\033[H\033[2J");
|
||||||
|
|
||||||
switch (game.getWindow()) {
|
switch (game.getWindow()) {
|
||||||
|
// Different screens: Probably will need a rewrite
|
||||||
case INVENTORY -> game.getInventory().renderFull(main, terminal, spriteList, true, Optional.empty());
|
case INVENTORY -> game.getInventory().renderFull(main, terminal, spriteList, true, Optional.empty());
|
||||||
case CRAFTING_TABLE -> game.getGameStates().craftingTable.render(main, terminal, spriteList);
|
case CRAFTING_TABLE -> game.getGameStates().craftingTable.render(main, terminal, spriteList);
|
||||||
case CHEST -> ((Chest) game.getWorld()[game.getGameStates().clickY][game.getGameStates().clickX].stream()
|
case CHEST -> ((Chest) game.getWorld()[game.getGameStates().clickY][game.getGameStates().clickX].stream()
|
||||||
@ -80,7 +81,7 @@ public class ScreenRenderer {
|
|||||||
case FURNACE -> ((Furnace) game.getWorld()[game.getGameStates().clickY][game.getGameStates().clickX]
|
case FURNACE -> ((Furnace) game.getWorld()[game.getGameStates().clickY][game.getGameStates().clickX]
|
||||||
.stream().filter(i -> i.getBlockId().equals("furnace")).toList().getFirst().getData()).render(game,
|
.stream().filter(i -> i.getBlockId().equals("furnace")).toList().getFirst().getData()).render(game,
|
||||||
main, terminal, spriteList);
|
main, terminal, spriteList);
|
||||||
case ESC -> Escape.render(main, terminal);
|
case ESC -> game.getGameStates().dependencies.escape.render(main, terminal, game);
|
||||||
case WORLD -> {
|
case WORLD -> {
|
||||||
// World
|
// World
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user