feat: Better ore generation

This commit is contained in:
Jakub Žitník 2025-03-10 18:18:04 +01:00
parent b04e73dee3
commit b18c77f707
Signed by: jzitnik
GPG Key ID: C577A802A6AF4EF3
3 changed files with 62 additions and 22 deletions

View File

@ -11,7 +11,7 @@ import java.util.Arrays;
@BlockRegistry("gold_ore") @BlockRegistry("gold_ore")
public class GoldOreBlock extends Block { public class GoldOreBlock extends Block {
public GoldOreBlock() { public GoldOreBlock() {
super("gold_ore", SpriteLoader.SPRITES.GOLD_BLOCK, 15, ItemType.PICKAXE, super("gold_ore", SpriteLoader.SPRITES.GOLD_ORE, 15, ItemType.PICKAXE,
Arrays.stream(ToolVariant.values()).toList()); Arrays.stream(ToolVariant.values()).toList());
} }
} }

View File

@ -33,6 +33,8 @@ public class Generation {
// Spawn player at a valid starting point // Spawn player at a valid starting point
world[terrainHeight[256] - 1][256].add(steveBlock2); world[terrainHeight[256] - 1][256].add(steveBlock2);
world[terrainHeight[256] - 2][256].add(steveBlock); world[terrainHeight[256] - 2][256].add(steveBlock);
game.getInventory().addItem(ItemBlockSupplier.getItem("diamond_pickaxe"));
} }
private static void initializeWorld(List<Block>[][] world) { private static void initializeWorld(List<Block>[][] world) {

View File

@ -63,7 +63,7 @@ public class PopulateWorld {
} }
// Generate ores // Generate ores
generateOres(world, isCave); generateOres(world, isCave, terrainHeight);
// Fill air blocks // Fill air blocks
for (List<Block>[] column : world) { for (List<Block>[] column : world) {
@ -73,28 +73,34 @@ public class PopulateWorld {
} }
} }
private static void generateOres(List<Block>[][] world, boolean[][] isCave) { private static void generateOres(List<Block>[][] world, boolean[][] isCave, int[] terrainHeight) {
Random random = new Random(); Random random = new Random();
// Ore configs: name, minY, maxY, minVeinSize, maxVeinSize, frequency // oreName, minVeinSize, maxVeinSize, frequency, extraDepthOffset
String[][] ores = { String[][] ores = {
{"coal_ore", "100", "220", "6", "15", "100"}, // More veins, bigger sizes {"coal_ore", "5", "8", "100", "0"},
{"iron_ore", "110", "220", "4", "10", "80"}, {"iron_ore", "4", "6", "80", "10"},
{"gold_ore", "120", "230", "3", "7", "50"}, {"gold_ore", "3", "5", "50", "20"},
{"diamond_ore", "130", "240", "2", "5", "30"}, {"diamond_ore", "2", "4", "30", "40"}, // diamonds spawn 40+ blocks deeper
}; };
for (String[] ore : ores) { for (String[] ore : ores) {
String oreName = ore[0]; String oreName = ore[0];
int minY = Integer.parseInt(ore[1]); int minVeinSize = Integer.parseInt(ore[1]);
int maxY = Integer.parseInt(ore[2]); int maxVeinSize = Integer.parseInt(ore[2]);
int minVeinSize = Integer.parseInt(ore[3]); int frequency = Integer.parseInt(ore[3]);
int maxVeinSize = Integer.parseInt(ore[4]); int depthOffset = Integer.parseInt(ore[4]);
int frequency = Integer.parseInt(ore[5]);
for (int i = 0; i < frequency; i++) { for (int i = 0; i < frequency; i++) {
int x = random.nextInt(WORLD_WIDTH); int x = random.nextInt(WORLD_WIDTH);
int y = minY + random.nextInt(maxY - minY + 1);
// Minimum Y now includes extra depth offset
int minY = terrainHeight[x] + 10 + depthOffset;
int maxY = Math.min(WORLD_HEIGHT - 2, minY + 60); // reduce max spread depth too
if (minY >= WORLD_HEIGHT - 2) continue; // skip if too deep
int y = minY + random.nextInt(Math.max(1, maxY - minY));
int veinSize = minVeinSize + random.nextInt(maxVeinSize - minVeinSize + 1); int veinSize = minVeinSize + random.nextInt(maxVeinSize - minVeinSize + 1);
generateOreVein(world, isCave, x, y, oreName, veinSize); generateOreVein(world, isCave, x, y, oreName, veinSize);
@ -106,21 +112,53 @@ public class PopulateWorld {
private static void generateOreVein(List<Block>[][] world, boolean[][] isCave, int startX, int startY, String oreName, int veinSize) { private static void generateOreVein(List<Block>[][] world, boolean[][] isCave, int startX, int startY, String oreName, int veinSize) {
Random random = new Random(); Random random = new Random();
for (int i = 0; i < veinSize; i++) { int x = startX;
int dx = startX + random.nextInt(3) - 1; int y = startY;
int dy = startY + random.nextInt(3) - 1;
if (dx >= 0 && dx < WORLD_WIDTH && dy >= 0 && dy < WORLD_HEIGHT - 1) { int placed = 0;
System.out.println("Placed " + oreName + " at (" + dx + ", " + dy + ")"); int attempts = 0;
// Only place ore if it's inside stone and not cave int maxAttempts = veinSize * 10; // failsafe to prevent infinite loop
List<Block> blockList = world[dy][dx];
while (placed < veinSize && attempts < maxAttempts) {
attempts++;
if (x >= 0 && x < WORLD_WIDTH && y >= 0 && y < WORLD_HEIGHT - 1) {
List<Block> blockList = world[y][x];
boolean placedHere = false;
for (int j = 0; j < blockList.size(); j++) { for (int j = 0; j < blockList.size(); j++) {
Block b = blockList.get(j); Block b = blockList.get(j);
if (b.getBlockId().equals("stone") && !isCave[dy][dx]) { if (b.getBlockId().equals("stone") && !isCave[y][x]) {
blockList.set(j, ItemBlockSupplier.getBlock(oreName)); blockList.set(j, ItemBlockSupplier.getBlock(oreName));
placed++;
placedHere = true;
break; break;
} }
} }
// Only continue walk if we successfully placed, otherwise try different direction
if (placedHere) {
int direction = random.nextInt(4);
switch (direction) {
case 0: x += 1; break;
case 1: x -= 1; break;
case 2: y += 1; break;
case 3: y -= 1; break;
}
// Optional: small branching
if (random.nextDouble() < 0.1 && placed < veinSize - 3) {
generateOreVein(world, isCave, x, y, oreName, 2); // small branch
placed += 2;
}
} else {
// Jump randomly to find another stone block to continue vein
x = startX + random.nextInt(5) - 2;
y = startY + random.nextInt(5) - 2;
}
} else {
// Jump back near the original vein start if out of bounds
x = startX + random.nextInt(5) - 2;
y = startY + random.nextInt(5) - 2;
} }
} }
} }