feat: Implemented inventory

This commit is contained in:
Jakub Žitník 2025-02-20 21:18:43 +01:00
parent 07ef87d42b
commit c6b4af7f72
Signed by: jzitnik
GPG Key ID: C577A802A6AF4EF3
17 changed files with 572 additions and 151 deletions

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# 2DCraft
2D craft is simple game written in Java running in terminal using ANSI art.

View File

@ -3,6 +3,7 @@ package cz.jzitnik;
import cz.jzitnik.game.Game;
import cz.jzitnik.game.MouseHandler;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.sprites.Window;
import cz.jzitnik.tui.ScreenRenderer;
import org.jline.terminal.MouseEvent;
import org.jline.terminal.Terminal;
@ -42,12 +43,26 @@ public class Main {
key = terminal.reader().read();
if (key == 'M') {
MouseEvent mouseEvent = terminal.readMouseEvent();
mouseHandler.handle(mouseEvent);
switch (game.getWindow()) {
case WORLD -> mouseHandler.handle(mouseEvent);
case INVENTORY -> game.getInventory().click(mouseEvent, terminal, screenRenderer, game);
}
}
}
}
switch (key) {
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
game.changeSlot(key - 49, screenRenderer);
break;
case 'a':
game.movePlayerLeft(screenRenderer);
screenRenderer.render(game);
@ -60,6 +75,15 @@ public class Main {
game.movePlayerUp(screenRenderer);
screenRenderer.render(game);
break;
case 'e':
if (game.getWindow() != Window.WORLD) {
game.setWindow(Window.WORLD);
game.getInventory().setSelectedItemInv(-1);
} else {
game.setWindow(Window.INVENTORY);
}
screenRenderer.render(game);
break;
case 'q':
System.out.println("Exiting game...");
isRunning[0] = false;
@ -77,7 +101,10 @@ public class Main {
// Game loop (rendering the game)
while (isRunning[0]) {
if (game.getWindow() == Window.WORLD) {
// Rerender the game only when default window
screenRenderer.render(game);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {

View File

@ -43,16 +43,22 @@ public class Block {
this.toolVariants = toolVariants;
}
public Block(String blockId, SpriteLoader.SPRITES sprite, int hardness, ItemType tool, List<ToolVariant> toolVariants, List<Item> drops) {
this.blockId = blockId;
this.sprite = sprite;
this.hardness = hardness;
this.tool = Optional.of(tool);
this.toolVariants = toolVariants;
this.drops = drops;
}
public void setSpriteState(Enum spriteState) {
this.spriteState = Optional.of(spriteState);
}
public int calculateHardness(Inventory inventory) {
int holdingDecrease = 0;
if (inventory.getItemInHand().isPresent() && tool.isPresent() && inventory.getItemInHand().get().getType().equals(tool.get())) {
holdingDecrease = inventory.getItemInHand().get().getMiningDecrease();
}
int decrease = hardness - holdingDecrease;
if (decrease < 0) {
decrease = 0;
}
return decrease;
}
}

View File

@ -3,6 +3,7 @@ package cz.jzitnik.game;
import cz.jzitnik.game.items.Item;
import cz.jzitnik.game.items.ItemType;
import cz.jzitnik.game.sprites.Breaking;
import cz.jzitnik.game.sprites.Window;
import cz.jzitnik.tui.ScreenMovingCalculationProvider;
import cz.jzitnik.tui.ScreenRenderer;
import lombok.Getter;
@ -18,6 +19,8 @@ public class Game {
@Setter
private Block player;
private boolean mining = false;
@Setter
private Window window = Window.WORLD;
private Inventory inventory = new Inventory();
@ -25,21 +28,6 @@ public class Game {
Generation.generateWorld(this);
}
public int calculateHardness(Block block) {
int holdingDecrease = 0;
if (inventory.getItemInHand().isPresent() && block.getTool().isPresent() && inventory.getItemInHand().get().getType().equals(block.getTool().get())) {
holdingDecrease = inventory.getItemInHand().get().getMiningDecrease();
}
int decrease = block.getHardness() - holdingDecrease;
if (decrease < 0) {
decrease = 0;
}
return decrease;
}
public int[] getPlayerCords() {
for (int i = 0; i < world.length; i++) {
for (int j = 0; j < world[i].length; j++) {
@ -54,6 +42,9 @@ public class Game {
}
public void movePlayerRight(ScreenRenderer screenRenderer) {
if (window != Window.WORLD) {
return;
}
int[] cords = getPlayerCords();
if (world[cords[1]][cords[0] + 1].stream().anyMatch(block -> !block.isGhost())) {
@ -62,11 +53,15 @@ public class Game {
world[cords[1]][cords[0] + 1].add(player);
world[cords[1]][cords[0]].remove(player);
screenRenderer.render(this);
update(screenRenderer);
}
public void movePlayerLeft(ScreenRenderer screenRenderer) {
if (window != Window.WORLD) {
return;
}
int[] cords = getPlayerCords();
if (world[cords[1]][cords[0] - 1].stream().anyMatch(block -> !block.isGhost())) {
@ -75,11 +70,15 @@ public class Game {
world[cords[1]][cords[0] - 1].add(player);
world[cords[1]][cords[0]].remove(player);
screenRenderer.render(this);
update(screenRenderer);
}
public void movePlayerUp(ScreenRenderer screenRenderer) {
if (window != Window.WORLD) {
return;
}
int[] cords = getPlayerCords();
if (world[cords[1] - 1][cords[0]].stream().anyMatch(block -> !block.isGhost()) || world[cords[1] + 1][cords[0]].stream().anyMatch(Block::isGhost)) {
@ -107,7 +106,7 @@ public class Game {
}
public void mine(ScreenRenderer screenRenderer, int x, int y) {
if (mining) {
if (mining || window != Window.WORLD) {
return;
}
@ -115,7 +114,7 @@ public class Game {
world[y][x].add(breakingBlock);
screenRenderer.render(this);
int hardness = calculateHardness(world[y][x].stream().filter(block -> !block.isGhost()).toList().get(0));
int hardness = world[y][x].stream().filter(block -> !block.isGhost()).toList().get(0).calculateHardness(inventory);
this.mining = true;
@ -200,7 +199,7 @@ public class Game {
public void update(ScreenRenderer screenRenderer) {
while (true) {
try {
Thread.sleep(200);
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
@ -218,8 +217,23 @@ public class Game {
}
public void build(int x, int y, ScreenRenderer screenRenderer) {
if (window != Window.WORLD) {
return;
}
var blocks = world[y][x];
int[] cords = getPlayerCords();
int playerX = cords[0];
int playerY = cords[1];
int distanceX = Math.abs(playerX - x);
int distanceY = Math.abs(playerY - y);
if (distanceX > 5 || distanceY > 5) {
return;
}
if (!blocks.stream().allMatch(Block::isGhost)) {
return;
}
@ -231,6 +245,16 @@ public class Game {
blocks.removeAll(blocks.stream().filter(block -> block.getBlockId().equals("air")).toList());
blocks.add(inventory.getItemInHand().get().getBlock().get());
inventory.decreaseItemInHand();
screenRenderer.render(this);
}
public void changeSlot(int slot, ScreenRenderer screenRenderer) {
if (window != Window.WORLD) {
return;
}
inventory.setItemInhHandIndex(slot);
screenRenderer.render(this);
}
}

View File

@ -10,19 +10,24 @@ import java.util.List;
import java.util.Random;
public class Generation {
private static Block dirt() {
public static Block dirt() {
var block = new Block("dirt", SpriteLoader.SPRITES.DIRT, 1, ItemType.SHOVEL, new ArrayList<>());
block.setDrops(List.of(new Item("Dirt block", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_DIRT, block)));
block.setDrops(List.of(new Item("dirt", "Dirt block", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_DIRT, block)));
return block;
}
private static Block grass() {
var block = new Block("grass", SpriteLoader.SPRITES.GRASS, 1, ItemType.SHOVEL, new ArrayList<>());
block.setDrops(List.of(new Item("Dirt block", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_DIRT, block)));
block.setDrops(List.of(new Item("dirt", "Dirt block", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_DIRT, dirt())));
return block;
}
private static Block stone() {
var block = new Block("stone", SpriteLoader.SPRITES.STONE, 15, ItemType.PICKAXE, Arrays.stream(ToolVariant.values()).toList());
block.setDrops(List.of(new Item("Stone block", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_DIRT, block)));
block.setDrops(List.of(new Item("stone", "Stone block", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_DIRT, block)));
return block;
}
private static Block oakLog() {
var block = new Block("oak_log", SpriteLoader.SPRITES.OAK_LOG, 3, ItemType.AXE, new ArrayList<>());
block.setDrops(List.of(new Item("oak_log", "Oak log", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_OAK_LOG, block)));
return block;
}
@ -104,7 +109,7 @@ public class Generation {
for (int j = 0; j < 3; j++) {
if (treeBase - j >= 0) {
world[treeBase - j - 1][i].add(new Block("oak_log", SpriteLoader.SPRITES.OAK_LOG, 2, ItemType.AXE, List.of(ToolVariant.IRON)));
world[treeBase - j - 1][i].add(oakLog());
}
}

View File

@ -2,10 +2,13 @@ package cz.jzitnik.game;
import cz.jzitnik.game.items.InventoryItem;
import cz.jzitnik.game.items.Item;
import cz.jzitnik.tui.ScreenRenderer;
import cz.jzitnik.tui.SpriteCombiner;
import cz.jzitnik.game.sprites.Number;
import cz.jzitnik.game.sprites.ui.Number;
import cz.jzitnik.tui.SpriteList;
import lombok.Getter;
import lombok.Setter;
import org.jline.terminal.MouseEvent;
import org.jline.terminal.Terminal;
import java.util.ArrayList;
@ -15,29 +18,83 @@ import java.util.Optional;
@Getter
public class Inventory {
private static final int INVENTORY_SIZE_PX = 470;
private static int COLUMN_AMOUNT = 5;
private static int ROW_AMOUNT = 4;
private List<InventoryItem> items = new ArrayList<>();
private InventoryItem[] items = new InventoryItem[20];
private InventoryItem[] hotbar = new InventoryItem[9];
@Setter
private int itemInhHandIndex = 0;
@Setter
private int selectedItemInv = -1;
public Optional<Item> getItemInHand() {
if (hotbar[itemInhHandIndex] == null) {
return Optional.empty();
}
return Optional.of(hotbar[itemInhHandIndex].getItem());
}
public void decreaseItemInHand() {
if (hotbar[itemInhHandIndex] == null) {
return;
}
if (hotbar[itemInhHandIndex].getAmount() == 1) {
hotbar[itemInhHandIndex] = null;
return;
}
hotbar[itemInhHandIndex].setAmount(hotbar[itemInhHandIndex].getAmount() - 1);
}
private void placeItem(Item item) {
var inventoryItem = new InventoryItem(item);
// Try to place to hotbar
for (int i = 0; i < hotbar.length; i++) {
if (hotbar[i] == null) {
hotbar[i] = inventoryItem;
return;
}
}
// Try to place to inventory
for (int i = 0; i < items.length; i++) {
if (items[i] == null) {
items[i] = inventoryItem;
break;
}
}
// If inventory is full the item is lost
}
public void addItem(Item item) {
if (!item.isStackable()) {
items.add(new InventoryItem(item));
placeItem(item);
return;
}
var it = items.stream().filter(i -> i.getItem().equals(item)).toList();
if (!it.isEmpty()) {
it.get(0).setAmount(it.get(0).getAmount() + 1);
// Try to stack in hotbar
for (InventoryItem value : hotbar) {
if (value != null && value.getItem().equals(item) && value.getAmount() < item.getStackAmount()) {
value.setAmount(value.getAmount() + 1);
return;
}
}
items.add(new InventoryItem(item));
// Try to stack in inventory
for (InventoryItem inventoryItem : items) {
if (inventoryItem != null && inventoryItem.getItem().equals(item) && inventoryItem.getAmount() < item.getStackAmount()) {
inventoryItem.setAmount(inventoryItem.getAmount() + 1);
return;
}
}
// If stacking didn't work try to add it to inventory
placeItem(item);
}
private Number.NumberState getNumberState(int digit) {
@ -77,16 +134,47 @@ public class Inventory {
return SpriteCombiner.combineTwoSprites( Number.fixForHotbar(nm.getSprite(numberState1), 2), Number.fixForHotbar(nm.getSprite(numberState2), 1));
}
public void renderHotbar(StringBuilder buffer, SpriteList spriteList, Terminal terminal) {
private String getHotbarBackground() {
StringBuilder sprite = new StringBuilder();
for (int i = 0; i < 25; i++) {
sprite.append("\033[38;5;245;48;5;245m▓".repeat(50));
sprite.append("\n");
}
return sprite.toString();
}
public void renderHotbar(StringBuilder buffer, SpriteList spriteList, Terminal terminal, boolean isFull) {
int termWidth = terminal.getWidth();
int startLeft = (termWidth / 2) - (INVENTORY_SIZE_PX / 2);
List<String> sprites = items.subList(0, Math.min(9, items.size())).stream().map(
items -> SpriteCombiner.combineTwoSprites(
spriteList.getSprite(items.getItem().getSprite()).getSprite(),
getNumberSprite(items.getAmount())
)
).toList();
List<String> sprites = new ArrayList<>();
for (int i = 0; i < hotbar.length; i++) {
var item = hotbar[i];
if (item == null) {
if (i == itemInhHandIndex && !isFull) {
sprites.add(getHotbarBackground());
continue;
}
sprites.add(null);
continue;
}
if (i == (isFull ? selectedItemInv - 20 : itemInhHandIndex)) {
sprites.add(SpriteCombiner.combineTwoSprites(getHotbarBackground(), SpriteCombiner.combineTwoSprites(
spriteList.getSprite(item.getItem().getSprite()).getSprite(),
getNumberSprite(item.getAmount())
)));
continue;
}
sprites.add(SpriteCombiner.combineTwoSprites(
spriteList.getSprite(item.getItem().getSprite()).getSprite(),
getNumberSprite(item.getAmount())
));
}
for (int i = 0; i < 26; i++) {
// Empty left space
@ -97,7 +185,7 @@ public class Inventory {
} else {
for (int j = 0; j < 9; j++) {
buffer.append("\033[38;5;231;48;5;231m▓".repeat(2));
if (sprites.size() <= j) {
if (sprites.get(j) == null) {
buffer.append("\033[0m ".repeat(50));
continue;
}
@ -110,4 +198,143 @@ public class Inventory {
buffer.append("\033[0m\n");
}
}
public void renderFull(StringBuilder buffer, Terminal terminal, SpriteList spriteList) {
int widthPixels = COLUMN_AMOUNT * (50 + 4) + 2;
int heightPixels = ROW_AMOUNT * (25 + 1);
int moveLeft = (terminal.getWidth() / 2) - (widthPixels / 2);
int moveTop = (terminal.getHeight() / 2) - (heightPixels / 2);
List<String> sprites = new ArrayList<>();
for (int i = 0; i < items.length; i++) {
var item = items[i];
if (item == null) {
if (i == selectedItemInv) {
sprites.add(getHotbarBackground());
continue;
}
sprites.add(null);
continue;
}
if (i == selectedItemInv) {
sprites.add(SpriteCombiner.combineTwoSprites(getHotbarBackground(), SpriteCombiner.combineTwoSprites(
spriteList.getSprite(item.getItem().getSprite()).getSprite(),
getNumberSprite(item.getAmount())
)));
continue;
}
sprites.add(SpriteCombiner.combineTwoSprites(
spriteList.getSprite(item.getItem().getSprite()).getSprite(),
getNumberSprite(item.getAmount())
));
}
// Top center
buffer.append("\n".repeat(Math.max(0, moveTop)));
buffer.append("\033[0m ".repeat(moveLeft));
buffer.append("\033[38;5;231;48;5;231m▓".repeat(widthPixels)).append("\033[0m\n");
for (int i = 0; i < ROW_AMOUNT; i++) {
for (int j = 0; j < 25; j++) {
buffer.append("\033[0m ".repeat(moveLeft));
buffer.append("\033[38;5;231;48;5;231m▓");
for (int k = 0; k < COLUMN_AMOUNT; k++) {
buffer.append("\033[38;5;231;48;5;231m▓".repeat(2));
var item = items[i * COLUMN_AMOUNT + k];
if (item == null) {
buffer.append("\033[0m ".repeat(50));
buffer.append("\033[38;5;231;48;5;231m▓".repeat(2));
continue;
}
var sprite = sprites.get(i * COLUMN_AMOUNT + k).split("\n");
buffer.append(sprite[j]);
buffer.append("\033[38;5;231;48;5;231m▓".repeat(2));
}
buffer.append("\033[38;5;231;48;5;231m▓");
buffer.append("\n");
}
buffer.append("\033[0m ".repeat(moveLeft));
buffer.append("\033[38;5;231;48;5;231m▓".repeat(widthPixels)).append("\n");
}
buffer.append("\n".repeat(10));
renderHotbar(buffer, spriteList, terminal, true);
}
public void click(MouseEvent mouseEvent, Terminal terminal, ScreenRenderer screenRenderer, Game game) {
if (mouseEvent.getType() != MouseEvent.Type.Pressed) {
return;
}
int x = mouseEvent.getX();
int y = mouseEvent.getY();
int widthPixels = COLUMN_AMOUNT * (50 + 4) + 2;
int heightPixels = ROW_AMOUNT * (25 + 1);
int moveLeft = (terminal.getWidth() / 2) - (widthPixels / 2);
int moveTop = (terminal.getHeight() / 2) - (heightPixels / 2);
int fx = x - moveLeft;
int fy = y - moveTop;
int startLeftHotbar = (terminal.getWidth() / 2) - (INVENTORY_SIZE_PX / 2);
int startTopHotbar = moveTop + heightPixels + 10;
if (x >= startLeftHotbar && y >= startTopHotbar && x <= startLeftHotbar + INVENTORY_SIZE_PX && y <= startTopHotbar + 26) {
int index = (x - startLeftHotbar) / 51;
if (hotbar[index] == null && selectedItemInv != -1) {
if (selectedItemInv < 20) {
hotbar[index] = items[selectedItemInv];
items[selectedItemInv] = null;
} else {
int in = selectedItemInv - 20;
hotbar[index] = hotbar[in];
hotbar[in] = null;
}
} else if (hotbar[index] != null) {
selectedItemInv = 20 + index;
}
screenRenderer.render(game);
return;
}
if (!(fx >= 0 && fx <= widthPixels && fy >=0 && fy <= heightPixels)) {
return;
}
switch (mouseEvent.getButton()) {
case Button1 -> {
int blockX = fx / 54;
int blockY = fy / 26;
InventoryItem inventoryItem = items[blockY * COLUMN_AMOUNT + blockX];
if (inventoryItem != null) {
selectedItemInv = blockY * COLUMN_AMOUNT + blockX;
}
if (inventoryItem == null && selectedItemInv != -1) {
if (selectedItemInv < 20) {
items[blockY * COLUMN_AMOUNT + blockX] = items[selectedItemInv];
items[selectedItemInv] = null;
} else {
int index = selectedItemInv - 20;
items[blockY * COLUMN_AMOUNT + blockX] = hotbar[index];
hotbar[index] = null;
}
}
}
}
screenRenderer.render(game);
}
}

View File

@ -1,5 +1,6 @@
package cz.jzitnik.game;
import cz.jzitnik.game.sprites.Window;
import cz.jzitnik.tui.ScreenMovingCalculationProvider;
import cz.jzitnik.tui.ScreenRenderer;
import lombok.AllArgsConstructor;
@ -22,14 +23,21 @@ public class MouseHandler {
return;
}
if (mouseEvent.getButton() == MouseEvent.Button.Button2 && mouseEvent.getType() == MouseEvent.Type.Pressed) {
if (mouseEvent.getButton() == MouseEvent.Button.Button3 && mouseEvent.getType() == MouseEvent.Type.Pressed) {
rightClick(mouseEvent);
return;
}
if (mouseEvent.getType() == MouseEvent.Type.Moved) {
move(mouseEvent);
return;
}
if (mouseEvent.getType() == MouseEvent.Type.Wheel) {
scroll(mouseEvent);
}
}
private void scroll(MouseEvent mouseEvent) {
}
private void leftClick(MouseEvent mouseEvent) {
@ -78,7 +86,7 @@ public class MouseHandler {
}
private void move(MouseEvent mouseEvent) {
if (game.isMining()) {
if (game.isMining() || game.getWindow() != Window.WORLD) {
return;
}

View File

@ -1,7 +1,7 @@
package cz.jzitnik.game;
import cz.jzitnik.game.sprites.*;
import cz.jzitnik.game.sprites.items.DirtItem;
import cz.jzitnik.game.sprites.items.SimpleItem;
import cz.jzitnik.tui.Sprite;
import cz.jzitnik.tui.SpriteList;
@ -21,7 +21,8 @@ public class SpriteLoader {
OAK_LEAF,
// Items
ITEM_DIRT
ITEM_DIRT,
ITEM_OAK_LOG
}
public static final HashMap<SPRITES, Sprite> SPRITES_MAP = new HashMap<>();
@ -36,7 +37,9 @@ public class SpriteLoader {
SPRITES_MAP.put(SPRITES.BREAKING, new Breaking());
SPRITES_MAP.put(SPRITES.OAK_LOG, new OakLog());
SPRITES_MAP.put(SPRITES.OAK_LEAF, new OakLeaf());
SPRITES_MAP.put(SPRITES.ITEM_DIRT, new DirtItem());
SPRITES_MAP.put(SPRITES.ITEM_DIRT, new SimpleItem("dirt.ans"));
SPRITES_MAP.put(SPRITES.ITEM_OAK_LOG, new SimpleItem("oak_log.ans"));
}
public static SpriteList<SPRITES> load() {

View File

@ -5,12 +5,12 @@ import cz.jzitnik.game.SpriteLoader;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Objects;
import java.util.Optional;
@Getter
@AllArgsConstructor
public class Item {
private String id;
private String name;
private ItemType type;
private Optional<ToolVariant> toolVariant = Optional.empty();
@ -18,9 +18,11 @@ public class Item {
private boolean stackable = true;
private int durability;
private int miningDecrease = 0;
private int stackAmount = 64;
private Optional<Block> block;
public Item(String name, ItemType type, SpriteLoader.SPRITES sprite, Block block) {
public Item(String id, String name, ItemType type, SpriteLoader.SPRITES sprite, Block block) {
this.id = id;
this.name = name;
this.type = type;
this.sprite = sprite;
@ -36,11 +38,7 @@ public class Item {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Item item = (Item) o;
return stackable == item.stackable &&
durability == item.durability &&
miningDecrease == item.miningDecrease &&
Objects.equals(name, item.name) &&
type == item.type &&
Objects.equals(sprite, item.sprite);
return name.equals(item.name);
}
}

View File

@ -0,0 +1,6 @@
package cz.jzitnik.game.sprites;
public enum Window {
WORLD,
INVENTORY
}

View File

@ -1,14 +0,0 @@
package cz.jzitnik.game.sprites.items;
import cz.jzitnik.tui.ResourceLoader;
import cz.jzitnik.tui.Sprite;
public class DirtItem extends Sprite {
public String getSprite() {
return ResourceLoader.loadResource("items/dirt.ans");
}
public String getSprite(Enum key) {
throw new RuntimeException("Imposible state");
}
}

View File

@ -0,0 +1,20 @@
package cz.jzitnik.game.sprites.items;
import cz.jzitnik.tui.ResourceLoader;
import cz.jzitnik.tui.Sprite;
public class SimpleItem extends Sprite {
private String resource;
public SimpleItem(String resource) {
this.resource = resource;
}
public String getSprite() {
return ResourceLoader.loadResource("items/" + resource).replaceAll("\033\\[38;5;1;48;5;16m", "\033[0m");
}
public String getSprite(Enum key) {
throw new RuntimeException("Imposible state");
}
}

View File

@ -0,0 +1,27 @@
package cz.jzitnik.game.sprites.ui;
import cz.jzitnik.tui.ResourceLoader;
import cz.jzitnik.tui.Sprite;
public class Font extends Sprite {
public enum FontState {
A,B,C,D,E,F,G,H,I,J,K,
L,M,N,O,P,Q,R,S,T,U,V,
W,X,Y,Z,a,b,c,d,e,f,g,
h,i,j,k,l,m,n,o,p,q,r,
s,t,u,v,w,x,y,z
}
public String getSprite() {
throw new RuntimeException("Invalid state");
}
public String getSprite(Enum key) {
// TODO: Implement font
String fullSprite = ResourceLoader.loadResource("ui/font.ans");
return null;
}
}

View File

@ -1,4 +1,4 @@
package cz.jzitnik.game.sprites;
package cz.jzitnik.game.sprites.ui;
import cz.jzitnik.tui.ResourceLoader;
import cz.jzitnik.tui.Sprite;

View File

@ -41,6 +41,11 @@ public class ScreenRenderer {
StringBuilder main = new StringBuilder();
main.append("\033[H\033[2J");
switch (game.getWindow()) {
case INVENTORY -> game.getInventory().renderFull(main, terminal, spriteList);
case WORLD -> {
// World
int[] cords = getPlayerCords(world);
if (cords == null) return;
@ -129,7 +134,9 @@ public class ScreenRenderer {
// Empty space between world and hotbar
main.append("\n\n\n");
game.getInventory().renderHotbar(main, spriteList, terminal);
game.getInventory().renderHotbar(main, spriteList, terminal, false);
}
}
System.out.println(main);
}

View File

@ -0,0 +1,26 @@
                                                  
                      ▒▒▒▒▒▒▒                     
                  ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒                 
              ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒             
          ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒         
      ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒     
   ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░  
   ▒▒░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░▒▒░░  
   ▒▒ ▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒░░▒▒░░  
   ▒▒ ▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒░░░▒▒░░  
   ▒▒░▒▒▒▒ ▒▒▒▒▒ ▒▒▒░▒▒▒▒▒▒▒▒▒▒▒  ▒░░▒░▒▒ ░░░▒▒▒  
   ▒▒▒░▒▒▒ ▒▒▒▒▒░▒▒▒░▒▒▒▒▒▒░▒▒░▒  ▒░░▒░▒▒░▒▒░▒▒▒  
   ▒▒▒░▒▒▒░▒▒▒▒▒▒▒░░░▒▒▒▒▒▒░▒░░▒░░▒░░▒░▒▒░▒▒░▒▒▒  
   ▒▒▒ ▒▒▒▒▒▒░▒▒▒▒▒ ░▒▒▒▒▒▒ ▒▒░▒  ▒░░▒░▒▒▒▒▒░▒▒▒  
   ▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒░░▒░░▒▒▒▒ ▒▒░▒░░▒▒▒▒▒▒▒░▒▒░ ▒▒  
   ▒▒▒░▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░▒▒▒▒▒░░▒▒░░░▒▒▒░▒▒░▒▒▒ ▒▒  
   ▒▒░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░▒▒▒▒▒░░▒▒▒▒░▒▒▒░▒▒░▒▒▒░▒▒  
   ▒▒░▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒░░▒  ▒▒▒▒░▒ ▒░▒▒ ▒▒▒░▒▒  
   ▒▒▒░▒▒▒▒▒▒ ▒▒▒▒░░▒▒▒▒▒░▒░ ░▒▒░░▒  ▒▒▒▒ ▒▒▒▒▒▒  
   ▒▒▒░▒▒▒▒▒▒ ▒▒▒▒ ░▒▒▒ ▒▒▒▒▒▒▒▒░░▒  ▒░▒▒░░░▒▒░░  
      ░▒▒▒▒▒▒░▒▒▒▒  ▒▒▒ ▒▒▒▒▒▒▒▒░░▒░░▒░▒▒▒░░▒     
          ▒▒▒ ▒▒░▒░░▒▒▒▒▒▒▒░▒▒▒▒▒▒▒  ▒░▒▒         
              ▒▒░▒░░░▒▒▒▒▒▒▒░░▒▒▒▒▒░░             
                  ▒▒░▒▒▒▒▒▒▒░░▒░▒                 
                      ▒▒▒▒▒▒░                     


View File

@ -0,0 +1,48 @@
    ▓▓▓▓       ▓▓▓▓▓▓▓▓▓▓       ▓▓▓▓▓▓▓▓   ▓▓▓▓▓▓▓▓▓▓▓   ▓▓▓▓▓▓▓▓▓▓▓▓░ ▓▓▓▓▓▓▓▓▓▓▓▓▓     ▓▓▓▓▓▓▓    ▓▓▓    ▓▓▓     ▓▓▓▓▓▓▓▓          ▓▓▓▓▓▓▓  ▓▓▓▓▓    ▓▓▓
  ▓▓▓▓▓▓▓       ▓▓▓▓   ░▓▓▓   ▒▓▓▓▓   ▓▓▓    ▓▓▓    ▓▓▓    ▓▓▓      ▓░   ▓▓▓▓     ▓▓   ▓▓▓▓▓  ▓▓▓▓  ▓▓▓    ▓▓▓       ▓▓▓▓              ▓▓▓░     ▓▓▓    ▓▓▓
▓▓▓▓   ░▓▓▓     ▓▓▓▓   ░▓▓▓  ▓▓▓▓            ▓▓▓    ▓▓▓    ▓▓▓  ▓▓       ▓▓▓▓ ▓▓     ▓▓▓▓▓          ▓▓▓    ▓▓▓       ▓▓▓▓              ▓▓▓░     ▓▓▓  ▓▓▓▓▓
▓▓▓▓   ░▓▓▓     ▓▓▓▓▓▓▓▓▓    ▓▓▓             ▓▓▓    ▓▓▓    ▓▓▓▓▓▓▓       ▓▓▓▓▓▓▓     ▓▓▓▓           ▓▓▓▓▓▓▓▓▓▓       ▓▓▓▓              ▓▓▓░     ▓▓▓▓▓▓▓▓  
▓▓▓▓▓▓▓▓▓▓▓     ▓▓▓▓   ░▓▓▓  ▓▓▓▓            ▓▓▓    ▓▓▓    ▓▓▓  ▓▓       ▓▓▓▓ ▓▓     ▓▓▓▓▓  ▓▓▓▓▓▓  ▓▓▓    ▓▓▓       ▓▓▓▓       ▓▓▓▒   ▓▓▓░     ▓▓▓  ▓▓▓▓▓
▓▓▓▓   ░▓▓▓     ▓▓▓▓   ░▓▓▓   ▒▓▓▓▓   ▓▓▓    ▓▓▓    ▓▓▓    ▓▓▓      ▓░   ▓▓▓▓          ▓▓▓▓▓  ▓▓▓▓  ▓▓▓    ▓▓▓       ▓▓▓▓       ▓▓▓▒   ▓▓▓░     ▓▓▓    ▓▓▓
▓▓▓▓   ░▓▓▓    ▓▓▓▓▓▓▓▓▓▓       ▓▓▓▓▓▓▓▓   ▓▓▓▓▓▓▓▓▓▓▓   ▓▓▓▓▓▓▓▓▓▓▓▓░ ▓▓▓▓▓▓▓           ▓▓▓▓▓▓▓▓▓  ▓▓▓    ▓▓▓     ▓▓▓▓▓▓▓▓       ▓▓▓▓▓▓▓     ▓▓▓▓▓    ▓▓▓
                                                                                                                                                          
▓▓▓▓▓▓▓▓       ▓▓▓     ░▓▓▓  ▓▓▓      ▓▓▓     ░▓▓▓▓▓     ▓▓▓▓▓▓▓▓▓▓▓     ▓▓▓▓▓▓▓     ▓▓▓▓▓▓▓▓▓▓▓     ▓▓▓▓▓▓▓▒     ▓▓▓▓▓▓▓▓▓▓    ▓▓▓▒   ▓▓▓░   ▓▓▓▓   ▓▓▓▓ 
  ▓▓▓▓         ▓▓▓▓▓  ▓▓▓▓▓  ▓▓▓▓▓    ▓▓▓    ▓▓▓  ▓▓▓▓     ▓▓▓    ▓▓▓░ ▓▓▓▓   ▓▓▓▓     ▓▓▓▓   ▓▓▓▓  ▓▓▓    ▓▓▓    ▓░ ▓▓▓▓  ▓    ▓▓▓▒   ▓▓▓░   ▓▓▓▓   ▓▓▓▓ 
  ▓▓▓▓         ▓▓▓▓▓▓▓▓▓▓▓▓  ▓▓▓▓▓▓▓  ▓▓▓  ▓▓▓░     ▓▓▓    ▓▓▓    ▓▓▓░ ▓▓▓▓   ▓▓▓▓     ▓▓▓▓   ▓▓▓▓  ▓▓▓▓▓            ▓▓▓▓       ▓▓▓▒   ▓▓▓░   ▓▓▓▓   ▓▓▓▓ 
  ▓▓▓▓         ▓▓▓ ▓▓▓▓░▓▓▓  ▓▓▓ ▓▓▓▓▓▓▓▓  ▓▓▓░     ▓▓▓    ▓▓▓▓▓▓▓▓▓▓  ▓▓▓▓   ▓▓▓▓     ▓▓▓▓▓▓▓▓▓▓   ░▓▓▓▓▓▓▓▒        ▓▓▓▓       ▓▓▓▒   ▓▓▓░   ▓▓▓▓   ▓▓▓▓ 
  ▓▓▓▓    ▓▓▓  ▓▓▓     ░▓▓▓  ▓▓▓   ▒▓▓▓▓▓  ▓▓▓░     ▓▓▓    ▓▓▓         ▓▓▓▓ ▓▓▓▓▓▓     ▓▓▓▓▓▓▓▓         ▒▓▓▓▓▓       ▓▓▓▓       ▓▓▓▒   ▓▓▓░   ▓▓▓▓   ▓▓▓▓ 
  ▓▓▓▓   ▓▓▓▓  ▓▓▓     ░▓▓▓  ▓▓▓      ▓▓▓    ▓▓▓  ▓▓▓▓     ▓▓▓           ▓▓▓▓▓▓▓       ▓▓▓▓ ▓▓▓▓▓   ▓▓▓    ▓▓▓       ▓▓▓▓       ▓▓▓▒   ▓▓▓░     ▓▓▓▓▓▓▓   
▓▓▓▓▓▓▓▓▓▓▓▓▓  ▓▓▓     ░▓▓▓  ▓▓▓      ▓▓▓     ░▓▓▓▓▓     ▓▓▓▓▓▓▓            ▓▓▓▓▓▓   ▓▓▓▓▓▓   ▓▓▓▓   ▓▓▓▓▓▓▓▒      ▓▓▓▓▓▓▓▓     ▓▓▓▓▓▓▓▓▓▓░      ▓▓▓▓     
                                                                                                                                                          
▓▓▓▓     ▓▓▓▓  ▓▓▓     ░▓▓▓  ▓▓▓    ▓▓▓▓   ▓▓▓▓▓▓▓▓▓▓▓▓                ▓▓▓▓▓▓                            ▓▓▓▓▓                     ▓▓▓▓▓▓                 
▓▓▓▓     ▓▓▓▓  ▓▓▓     ░▓▓▓  ▓▓▓    ▓▓▓▓   ▓▓▓░   ▓▓▓▓▒                  ▓▓▓▓                              ▓▓▓                    ▓▓▓  ▓▓▓░               
▓▓▓▓     ▓▓▓▓   ▓▓▓▓  ▓▓▓▓   ▓▓▓    ▓▓▓▓   ▓▓▓  ▓▓▓▓▓      ▓▓▓▓▓▓▓       ▓▓▓▓▓▓▓▓▓     ▓▓▓▓▓▓▓             ▓▓▓     ▓▓▓▓▓▓▓▓       ▓▓▓           ▓▓▓▓▓▓ ▓▓▓
▓▓▓▓ ░▓▓▓▓▓▓▓     ▓▓▓▓▓▒      ░▓▓▓▓▓▓▓░      ▒▓▓▓▓░             ▓▓▓▓     ▓▓▓▓   ▓▓▓▓ ▓▓▓▓   ▓▓▓▓    ░▓▓▓▓▓▓▓▓▓    ▓▓▓    ▓▓▓    ▓▓▓▓▓▓▓       ▓▓▓▓   ▓▓▓▓ 
▓▓▓▓▓▓▓▓▓▓▓▓▓   ▓▓▓▓  ▓▓▓▓      ▓▓▓▓        ▓▓▓▓     ▓▓   ▓▓▓▓▓▓▓▓▓▓     ▓▓▓▓   ▓▓▓▓ ▓▓▓▓           ▓▓▓    ▓▓▓    ▓▓▓▓▓▓▓▓▓▓      ▓▓▓         ▓▓▓▓   ▓▓▓▓ 
▓▓▓▓▓▓ ░▓▓▓▓▓  ▓▓▓     ░▓▓▓     ▓▓▓▓       ▓▓▓░     ▓▓▓  ▓▓▓▓   ▓▓▓▓     ▓▓▓▓   ▓▓▓▓ ▓▓▓▓   ▓▓▓▓    ▓▓▓    ▓▓▓    ▓▓▓             ▓▓▓           ▓▓▓▓▓▓▓▓▓ 
▓▓▓▓     ▓▓▓▓  ▓▓▓     ░▓▓▓   ▒▓▓▓▓▓▓▓     ▓▓▓▓▓▓▓▓▓▓▓▓    ▓▓▓▓▓▓ ▓▓▓░ ▓▓▓▓ ▓▓▓▓▓▓     ▓▓▓▓▓▓▓       ▓▓▓▓▓▓░▓▓▓▓   ▓▓▓▓▓▓▓▓     ▓▓▓▓▓▓▓              ▓▓▓▓ 
                                                                                                                                              ▒▒▒░▒▒▒▒▒   
▓▓▓▓▓▓            ▓▓▓▓            ▓▓▓▓     ▓▓▓▓▓           ▓▓▓▓▓                                                                                          
  ▓▓▓▓                                       ▓▓▓             ▓▓▓                                                                                          
  ▓▓▓▓ ░▓▓▓     ▓▓▓▓▓▓        ▒▓▓▓▓▓▓▓       ▓▓▓    ▓▓▓      ▓▓▓       ▓▓▓▓▓▓ ▓▓▓▓   ▓▓▓▓▓▓▓▓▓       ▓▓▓▓▓▓▓▒     ▓▓▓ ▓▓▓▓▓▓      ▓▓▓▓▓▓ ▓▓▓  ▓▓▓▓░▓▓▓▓   
  ▓▓▓▓▓▓▓▓▓▓▓     ▓▓▓▓            ▓▓▓▓       ▓▓▓  ▓▓▓▓▓      ▓▓▓       ▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓   ▓▓▓▓    ▓▓▓    ▓▓▓     ▓▓▓▓    ▓▓▓  ▓▓▓▒   ▓▓▓░     ▓▓▓  ▓▓▓▓ 
  ▓▓▓▓   ▓▓▓▓     ▓▓▓▓            ▓▓▓▓       ▓▓▓▓▓▓▓▓        ▓▓▓       ▓▓▓▓ ▓▓  ▓▓▓▓ ▓▓▓▓   ▓▓▓▓    ▓▓▓    ▓▓▓     ▓▓▓▓    ▓▓▓  ▓▓▓▒   ▓▓▓░     ▓▓▓  ▓▓▓▓ 
  ▓▓▓▓   ▓▓▓▓     ▓▓▓▓            ▓▓▓▓       ▓▓▓  ▓▓▓▓▒      ▓▓▓       ▓▓▓▓     ▓▓▓▓ ▓▓▓▓   ▓▓▓▓    ▓▓▓    ▓▓▓     ▓▓▓▓▓▓▓▓▓      ▓▓▓▓▓▓▓▓░     ▓▓▓       
▓▓▓▓▓▓   ▓▓▓▓   ▓▓▓▓▓▓▓▒     ▓▓▓  ▓▓▓▓     ▓▓▓▓▓    ▓▓▓    ▓▓▓▓▓▓▓     ▓▓▓▓     ▓▓▓▓ ▓▓▓▓   ▓▓▓▓     ▓▓▓▓▓▓▓▒      ▓▓▓▓                ▓▓▓░   ▓▓▓▓▓▓▓     
                              ▓░░░░░                                                                              ░░░░░░░            ░░░░░░░              
                    ▓▓                                                                                             ▓▓▓▓▓▓▓▓        ▓▓▓▓         ▓▓▓▓▓▓▓   
                  ▓▓▓▓                                                                                            ▓▓▓    ▓▓▓    ▓▓▓▓▓▓▓       ▓▓▓▓   ▓▓▓▓ 
 ░▓▓▓▓▓▓▓▓▓     ▓▓▓▓▓▓▓▓▓    ▓▓▓    ▓▓▓▓   ▓▓▓░   ▓▓▓▓   ▓▓▓▓     ▓▓▓░ ▓▓▓▓░   ░▓▓▓▓ ▓▓▓▓   ▓▓▓▓    ▓▓▓▓▓▓▓▓▓▓    ▓▓▓ ░▓▓▓▓▓       ▓▓▓▓             ░▓▓▓▓ 
▓▓▓▓              ▓▓▓▓       ▓▓▓    ▓▓▓▓   ▓▓▓░   ▓▓▓▓   ▓▓▓▓     ▓▓▓░  ▒▓▓▓▓▓▓▓▓▓▒  ▓▓▓▓   ▓▓▓▓    ▓▒  ▓▓▓▓░     ▓▓▓▓▓▓▓▓▓▓       ▓▓▓▓          ▓▓▓▓▓▓▒  
  ▓▓▓▓▓▓▓▓        ▓▓▓▓       ▓▓▓    ▓▓▓▓   ▓▓▓░   ▓▓▓▓   ▓▓▓▓░▓▓▓ ▓▓▓░    ▓▓▓▓▓▓▓    ▓▓▓▓   ▓▓▓▓      ▓▓▓▓▓       ▓▓▓▓▓  ▓▓▓       ▓▓▓▓        ▓▓▓▓       
       ░▓▓▓       ▓▓▓▓ ░▓    ▓▓▓    ▓▓▓▓     ▓▓▓▓▓▓▓     ▓▓▓▓▓▓▓▓▓▓▓▓░  ▓▓▓▓▓ ▓▓▓▓▓    ▓▓▓▓▓▓▓▓▓    ░▓▓▓▓  ░▓▓    ▓▓▓    ▓▓▓       ▓▓▓▓       ▓▓▓▓   ▓▓▓▓ 
▓▓▓▓▓▓▓▓▓           ▓▓▓▒      ▒▓▓▓▓▓▓ ▓▓▓     ░▓▓▓         ▓▓▓  ▓▓▓▓   ▓▓▓▓     ▓▓▓▓        ▓▓▓▓    ▓▓▓▓▓▓▓▓▓▓     ▓▓▓▓▓▓▓▓     ▓▓▓▓▓▓▓▓▓▓░   ▓▓▓▓▓▓▓▓▓▓▓ 
                                                                                     ▒▒▒▒▒▒▒▒▒                                                            
  ▓▓▓▓▓▓▓           ▓▓▓▓▓    ▓▓▓▓▓▓▓▓▓▓▓      ░▓▓▓▓▓     ▓▓▓▓▓▓▓▓▓▓▓     ▓▓▓▓▓▓▓       ▓▓▓▓▓▓▓                                    ▓▓▓  ▓▓▓░     ▓▓▓  ▓▓▓▓ 
▓▓▓▓   ░▓▓▓       ▓▓▓▓▓▓▓    ▓▓▓             ▓▓▓▓        ▓▓▓▓   ▓▓▓▓   ▓▓▓▓   ▓▓▓▓   ▓▓▓▓   ▓▓▓▓                                  ▓▓▓  ▓▓▓░     ▓▓▓  ▓▓▓▓ 
       ░▓▓▓    ▒▓▓▓▓▓ ▓▓▓    ▓▓▓▓▓▓▓▓▓░    ▓▓▓▓                ░▓▓▓▓   ▓▓▓▓   ▓▓▓▓   ▓▓▓▓   ▓▓▓▓                                  ▓▓▓  ▓▓▓░     ▓▓▓  ▓▓▓▓ 
    ▓▓▓▓▓      ▓▓▓▓   ▓▓▓           ▓▓▓▓   ▓▓▓▓▓▓▓▓▓▓        ░▓▓▓▓▓      ▓▓▓▓▓▓▓      ▓▓▓▓▓▓▓▓▓▓                                                          
       ░▓▓▓    ▓▓▓▓▓▓▓▓▓▓▓▓         ▓▓▓▓   ▓▓▓░   ▓▓▓▓      ▓▓▓▓       ▓▓▓▓   ▓▓▓▓          ▓▓▓▓                                                          
▓▓▓▓   ░▓▓▓           ▓▓▓    ▓▓▓    ▓▓▓▓   ▓▓▓░   ▓▓▓▓     ▓▓▓         ▓▓▓▓   ▓▓▓▓        ▓▓▓▓           ▓▓▓▒        ▓▓▓▓▓▓                               
  ░░░░░▓░             ░░░     ▒░░░░░░░       ░▓░░░░░       ░░░           ░░░░░░░       ░░░░░░            ░░░▒        ░░▓▓▓░