feat: Started implementing crafting

This commit is contained in:
Jakub Žitník 2025-02-21 18:25:58 +01:00
parent c6b4af7f72
commit 1209092a9c
Signed by: jzitnik
GPG Key ID: C577A802A6AF4EF3
9 changed files with 294 additions and 119 deletions

View File

@ -3,6 +3,7 @@ package cz.jzitnik.game;
import cz.jzitnik.game.items.Item; import cz.jzitnik.game.items.Item;
import cz.jzitnik.game.items.ItemType; import cz.jzitnik.game.items.ItemType;
import cz.jzitnik.game.items.ToolVariant; import cz.jzitnik.game.items.ToolVariant;
import cz.jzitnik.game.ui.Inventory;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;

View File

@ -4,6 +4,7 @@ import cz.jzitnik.game.items.Item;
import cz.jzitnik.game.items.ItemType; import cz.jzitnik.game.items.ItemType;
import cz.jzitnik.game.sprites.Breaking; import cz.jzitnik.game.sprites.Breaking;
import cz.jzitnik.game.sprites.Window; import cz.jzitnik.game.sprites.Window;
import cz.jzitnik.game.ui.Inventory;
import cz.jzitnik.tui.ScreenMovingCalculationProvider; import cz.jzitnik.tui.ScreenMovingCalculationProvider;
import cz.jzitnik.tui.ScreenRenderer; import cz.jzitnik.tui.ScreenRenderer;
import lombok.Getter; import lombok.Getter;

View File

@ -1,36 +1,14 @@
package cz.jzitnik.game; package cz.jzitnik.game;
import cz.jzitnik.game.items.Item; import cz.jzitnik.game.items.Item;
import cz.jzitnik.game.items.ItemBlockGenerator;
import cz.jzitnik.game.items.ItemType; import cz.jzitnik.game.items.ItemType;
import cz.jzitnik.game.items.ToolVariant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
public class Generation { public class Generation {
public static Block dirt() {
var block = new Block("dirt", SpriteLoader.SPRITES.DIRT, 1, ItemType.SHOVEL, new ArrayList<>());
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", "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", "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;
}
public static void generateWorld(Game game) { public static void generateWorld(Game game) {
var world = game.getWorld(); var world = game.getWorld();
initializeWorld(world); initializeWorld(world);
@ -76,16 +54,16 @@ public class Generation {
for (int i = 0; i < 512; i++) { for (int i = 0; i < 512; i++) {
int hillHeight = terrainHeight[i]; int hillHeight = terrainHeight[i];
world[hillHeight][i].add(grass()); world[hillHeight][i].add(ItemBlockGenerator.Blocks.grass());
for (int j = 1; j <= 4; j++) { for (int j = 1; j <= 4; j++) {
if (hillHeight + j < 256) { if (hillHeight + j < 256) {
world[hillHeight + j][i].add(dirt()); world[hillHeight + j][i].add(ItemBlockGenerator.Blocks.dirt());
} }
} }
for (int j = hillHeight + 5; j < 250; j++) { for (int j = hillHeight + 5; j < 250; j++) {
world[j][i].add(stone()); world[j][i].add(ItemBlockGenerator.Blocks.stone());
} }
world[255][i].add(new Block("bedrock", SpriteLoader.SPRITES.BEDROCK)); world[255][i].add(new Block("bedrock", SpriteLoader.SPRITES.BEDROCK));
@ -109,7 +87,7 @@ public class Generation {
for (int j = 0; j < 3; j++) { for (int j = 0; j < 3; j++) {
if (treeBase - j >= 0) { if (treeBase - j >= 0) {
world[treeBase - j - 1][i].add(oakLog()); world[treeBase - j - 1][i].add(ItemBlockGenerator.Blocks.oakLog());
} }
} }

View File

@ -37,6 +37,7 @@ public class MouseHandler {
scroll(mouseEvent); scroll(mouseEvent);
} }
} }
private void scroll(MouseEvent mouseEvent) { private void scroll(MouseEvent mouseEvent) {
} }

View File

@ -0,0 +1,12 @@
package cz.jzitnik.game.crafting;
import cz.jzitnik.game.items.Item;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public class CraftingRecipe {
private String[] recipe;
private Item item;
}

View File

@ -0,0 +1,7 @@
package cz.jzitnik.game.crafting;
import java.util.List;
public class CraftingRecipeList {
private List<CraftingRecipe> recipes;
}

View File

@ -0,0 +1,59 @@
package cz.jzitnik.game.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.Block;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ItemBlockGenerator {
// This is necessary to not get infinite recursion
private static class Helper {
public static Item dirt(Block ref) {
return new Item("dirt", "Dirt block", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_DIRT, ref);
}
public static Item stone(Block ref) {
return new Item("stone", "Stone block", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_DIRT, ref);
}
public static Item oakLog(Block ref) {
return new Item("oak_log", "Oak log", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_OAK_LOG, ref);
}
}
public static class Blocks {
public static Block dirt() {
var block = new Block("dirt", SpriteLoader.SPRITES.DIRT, 1, ItemType.SHOVEL, new ArrayList<>());
block.setDrops(List.of(Helper.dirt(block)));
return block;
}
public static Block grass() {
var block = new Block("grass", SpriteLoader.SPRITES.GRASS, 1, ItemType.SHOVEL, new ArrayList<>());
block.setDrops(List.of(Items.dirt()));
return block;
}
public static Block stone() {
var block = new Block("stone", SpriteLoader.SPRITES.STONE, 15, ItemType.PICKAXE, Arrays.stream(ToolVariant.values()).toList());
block.setDrops(List.of(Helper.stone(block)));
return block;
}
public static Block oakLog() {
var block = new Block("oak_log", SpriteLoader.SPRITES.OAK_LOG, 3, ItemType.AXE, new ArrayList<>());
block.setDrops(List.of(Helper.oakLog(block)));
return block;
}
}
// I hate this but whatever
public static class Items {
public static Item dirt() {
return Helper.dirt(Blocks.dirt());
}
public static Item stone() {
return Helper.stone(Blocks.stone());
}
public static Item oakLog() {
return Helper.stone(Blocks.stone());
}
}
}

View File

@ -1,5 +1,6 @@
package cz.jzitnik.game; package cz.jzitnik.game.ui;
import cz.jzitnik.game.Game;
import cz.jzitnik.game.items.InventoryItem; import cz.jzitnik.game.items.InventoryItem;
import cz.jzitnik.game.items.Item; import cz.jzitnik.game.items.Item;
import cz.jzitnik.tui.ScreenRenderer; import cz.jzitnik.tui.ScreenRenderer;
@ -23,6 +24,7 @@ public class Inventory {
private InventoryItem[] items = new InventoryItem[20]; private InventoryItem[] items = new InventoryItem[20];
private InventoryItem[] hotbar = new InventoryItem[9]; private InventoryItem[] hotbar = new InventoryItem[9];
private SmallCraftingTable smallCraftingTable = new SmallCraftingTable( this);
@Setter @Setter
private int itemInhHandIndex = 0; private int itemInhHandIndex = 0;
@ -147,34 +149,7 @@ public class Inventory {
int termWidth = terminal.getWidth(); int termWidth = terminal.getWidth();
int startLeft = (termWidth / 2) - (INVENTORY_SIZE_PX / 2); int startLeft = (termWidth / 2) - (INVENTORY_SIZE_PX / 2);
List<String> sprites = new ArrayList<>(); List<String> sprites = getSprites(hotbar, spriteList, (isFull ? selectedItemInv - 20 : itemInhHandIndex));
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++) { for (int i = 0; i < 26; i++) {
// Empty left space // Empty left space
@ -206,34 +181,7 @@ public class Inventory {
int moveLeft = (terminal.getWidth() / 2) - (widthPixels / 2); int moveLeft = (terminal.getWidth() / 2) - (widthPixels / 2);
int moveTop = (terminal.getHeight() / 2) - (heightPixels / 2); int moveTop = (terminal.getHeight() / 2) - (heightPixels / 2);
List<String> sprites = new ArrayList<>(); List<String> sprites = getSprites(items, spriteList, selectedItemInv);
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 // Top center
buffer.append("\n".repeat(Math.max(0, moveTop))); buffer.append("\n".repeat(Math.max(0, moveTop)));
@ -241,10 +189,13 @@ public class Inventory {
buffer.append("\033[0m ".repeat(moveLeft)); buffer.append("\033[0m ".repeat(moveLeft));
buffer.append("\033[38;5;231;48;5;231m▓".repeat(widthPixels)).append("\033[0m\n"); buffer.append("\033[38;5;231;48;5;231m▓".repeat(widthPixels)).append("\033[0m\n");
String[] craftingTable = smallCraftingTable.render(spriteList).toString().split("\n");
int spacesFromTop = (ROW_AMOUNT - SmallCraftingTable.ROW_AMOUNT) / 2;
for (int i = 0; i < ROW_AMOUNT; i++) { for (int i = 0; i < ROW_AMOUNT; i++) {
for (int j = 0; j < 25; j++) { for (int j = 0; j < 26; j++) {
buffer.append("\033[0m ".repeat(moveLeft)); buffer.append("\033[0m ".repeat(moveLeft));
if (j < 25) {
buffer.append("\033[38;5;231;48;5;231m▓"); buffer.append("\033[38;5;231;48;5;231m▓");
for (int k = 0; k < COLUMN_AMOUNT; k++) { for (int k = 0; k < COLUMN_AMOUNT; k++) {
buffer.append("\033[38;5;231;48;5;231m▓".repeat(2)); buffer.append("\033[38;5;231;48;5;231m▓".repeat(2));
@ -259,10 +210,25 @@ public class Inventory {
buffer.append("\033[38;5;231;48;5;231m▓".repeat(2)); buffer.append("\033[38;5;231;48;5;231m▓".repeat(2));
} }
buffer.append("\033[38;5;231;48;5;231m▓"); buffer.append("\033[38;5;231;48;5;231m▓");
} else {
buffer.append("\033[38;5;231;48;5;231m▓".repeat(widthPixels));
if (i == 0) {
buffer.append("\033[0m").append(" ".repeat(20));
buffer.append("\033[38;5;231;48;5;231m▓".repeat(106));
}
}
if (i + 1 > spacesFromTop) {
int craftingIndex = ((i - spacesFromTop) * 26) + j;
if (craftingIndex >= 0 && craftingIndex < craftingTable.length) {
buffer.append("\033[0m").append(" ".repeat(20));
buffer.append(craftingTable[craftingIndex]);
}
}
buffer.append("\n"); 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)); buffer.append("\n".repeat(10));
@ -290,17 +256,19 @@ public class Inventory {
int startLeftHotbar = (terminal.getWidth() / 2) - (INVENTORY_SIZE_PX / 2); int startLeftHotbar = (terminal.getWidth() / 2) - (INVENTORY_SIZE_PX / 2);
int startTopHotbar = moveTop + heightPixels + 10; int startTopHotbar = moveTop + heightPixels + 10;
int startLeftCrafting = moveLeft + widthPixels + 20;
int startTopCrafting = moveTop + 26;
if (x >= startLeftCrafting && y >= startTopCrafting && y <= startTopCrafting + 52 && x <= startLeftCrafting + 106 + 54 + 7) {
smallCraftingTable.click(mouseEvent.getX() - startLeftCrafting, mouseEvent.getY() - startTopCrafting);
screenRenderer.render(game);
return;
}
if (x >= startLeftHotbar && y >= startTopHotbar && x <= startLeftHotbar + INVENTORY_SIZE_PX && y <= startTopHotbar + 26) { if (x >= startLeftHotbar && y >= startTopHotbar && x <= startLeftHotbar + INVENTORY_SIZE_PX && y <= startTopHotbar + 26) {
int index = (x - startLeftHotbar) / 51; int index = (x - startLeftHotbar) / 51;
if (hotbar[index] == null && selectedItemInv != -1) { if (hotbar[index] == null && selectedItemInv != -1) {
if (selectedItemInv < 20) { hotbar[index] = getSelectedItem();
hotbar[index] = items[selectedItemInv];
items[selectedItemInv] = null;
} else {
int in = selectedItemInv - 20;
hotbar[index] = hotbar[in];
hotbar[in] = null;
}
} else if (hotbar[index] != null) { } else if (hotbar[index] != null) {
selectedItemInv = 20 + index; selectedItemInv = 20 + index;
} }
@ -323,18 +291,64 @@ public class Inventory {
selectedItemInv = blockY * COLUMN_AMOUNT + blockX; selectedItemInv = blockY * COLUMN_AMOUNT + blockX;
} }
if (inventoryItem == null && selectedItemInv != -1) { if (inventoryItem == null && selectedItemInv != -1) {
if (selectedItemInv < 20) { items[blockY * COLUMN_AMOUNT + blockX] = getSelectedItem();
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); screenRenderer.render(game);
} }
public List<String> getSprites(InventoryItem[] items, SpriteList spriteList, int selectedItem) {
List<String> sprites = new ArrayList<>();
for (int i = 0; i < items.length; i++) {
var item = items[i];
if (item == null) {
if (i == selectedItem) {
sprites.add(getHotbarBackground());
continue;
}
sprites.add(null);
continue;
}
if (i == selectedItem) {
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())
));
}
return sprites;
}
public InventoryItem getSelectedItem() {
InventoryItem temp;
if (selectedItemInv < 20) {
temp = items[selectedItemInv];
items[selectedItemInv] = null;
} else if (selectedItemInv >= 29) {
int index = selectedItemInv - 29;
temp = smallCraftingTable.getItems()[index];
smallCraftingTable.getItems()[index] = null;
} else {
int index = selectedItemInv - 20;
temp = hotbar[index];
hotbar[index] = null;
}
selectedItemInv = -1;
return temp;
}
} }

View File

@ -0,0 +1,102 @@
package cz.jzitnik.game.ui;
import cz.jzitnik.game.Generation;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.items.InventoryItem;
import cz.jzitnik.game.items.Item;
import cz.jzitnik.game.items.ItemBlockGenerator;
import cz.jzitnik.game.items.ItemType;
import cz.jzitnik.tui.SpriteList;
import lombok.Getter;
import java.util.List;
import java.util.Optional;
public class SmallCraftingTable {
public static final int ROW_AMOUNT = 2;
public static final int COLUMN_AMOUNT = 2;
private Inventory inventory;
@Getter
private InventoryItem[] items = new InventoryItem[4];
public void click(int x, int y) {
if (x > 106) {
if (y > 10 && y < 37) {
// Pickup item from crafting table
return;
}
return;
}
int blockX = x / 53;
int blockY = y / 26;
int blockIndex = blockY * COLUMN_AMOUNT + blockX;
if (items[blockIndex] == null && inventory.getSelectedItemInv() != -1) {
items[blockIndex] = inventory.getSelectedItem();
} else if (items[blockIndex] != null) {
inventory.setSelectedItemInv(blockIndex + 29);
}
}
public StringBuilder render(SpriteList spriteList) {
var buf = new StringBuilder();
List<String> sprites = inventory.getSprites(items, spriteList, inventory.getSelectedItemInv() - 29);
Optional<Item> craftedItem = Optional.of(ItemBlockGenerator.Items.dirt());
String[] craftedSprite = craftedItem.isPresent() ? spriteList.getSprite(craftedItem.get().getSprite()).getSprite().split("\n") : null;
int counter = 0;
for (int i = 0; i < ROW_AMOUNT; i++) {
for (int j = 0; j < 26; j++) {
if (j == 25) {
buf.append("\033[38;5;231;48;5;231m▓".repeat(106));
} else {
for (int k = 0; k < COLUMN_AMOUNT; k++) {
buf.append("\033[38;5;231;48;5;231m▓".repeat(2));
String sprite = sprites.get(i * 2 + k);
if (sprite == null) {
buf.append("\033[0m ".repeat(50));
} else {
String[] spriteLines = sprite.split("\n");
buf.append(spriteLines[j]);
}
}
buf.append("\033[38;5;231;48;5;231m▓".repeat(2));
}
if (i == 0 && j > 10 || i == 1 && j < 12) {
buf.append("\033[0m").append(" ".repeat(7));
if (i == 0 && j - 11 == 0 || i == 1 && j == 11) {
buf.append("\033[38;5;231;48;5;231m▓".repeat(54));
} else {
buf.append("\033[38;5;231;48;5;231m▓".repeat(2));
if (craftedItem.isEmpty()) {
buf.append("\033[0m ".repeat(50));
} else {
buf.append(craftedSprite[counter]);
counter++;
}
buf.append("\033[38;5;231;48;5;231m▓".repeat(2));
}
}
buf.append("\n");
}
}
buf.append("\033[0m");
return buf;
}
public SmallCraftingTable(Inventory inventory) {
this.inventory = inventory;
}
}