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")
public class GoldOreBlock extends Block {
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());
}
}

View File

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

View File

@ -63,7 +63,7 @@ public class PopulateWorld {
}
// Generate ores
generateOres(world, isCave);
generateOres(world, isCave, terrainHeight);
// Fill air blocks
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();
// Ore configs: name, minY, maxY, minVeinSize, maxVeinSize, frequency
// oreName, minVeinSize, maxVeinSize, frequency, extraDepthOffset
String[][] ores = {
{"coal_ore", "100", "220", "6", "15", "100"}, // More veins, bigger sizes
{"iron_ore", "110", "220", "4", "10", "80"},
{"gold_ore", "120", "230", "3", "7", "50"},
{"diamond_ore", "130", "240", "2", "5", "30"},
{"coal_ore", "5", "8", "100", "0"},
{"iron_ore", "4", "6", "80", "10"},
{"gold_ore", "3", "5", "50", "20"},
{"diamond_ore", "2", "4", "30", "40"}, // diamonds spawn 40+ blocks deeper
};
for (String[] ore : ores) {
String oreName = ore[0];
int minY = Integer.parseInt(ore[1]);
int maxY = Integer.parseInt(ore[2]);
int minVeinSize = Integer.parseInt(ore[3]);
int maxVeinSize = Integer.parseInt(ore[4]);
int frequency = Integer.parseInt(ore[5]);
int minVeinSize = Integer.parseInt(ore[1]);
int maxVeinSize = Integer.parseInt(ore[2]);
int frequency = Integer.parseInt(ore[3]);
int depthOffset = Integer.parseInt(ore[4]);
for (int i = 0; i < frequency; i++) {
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);
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) {
Random random = new Random();
for (int i = 0; i < veinSize; i++) {
int dx = startX + random.nextInt(3) - 1;
int dy = startY + random.nextInt(3) - 1;
int x = startX;
int y = startY;
if (dx >= 0 && dx < WORLD_WIDTH && dy >= 0 && dy < WORLD_HEIGHT - 1) {
System.out.println("Placed " + oreName + " at (" + dx + ", " + dy + ")");
// Only place ore if it's inside stone and not cave
List<Block> blockList = world[dy][dx];
int placed = 0;
int attempts = 0;
int maxAttempts = veinSize * 10; // failsafe to prevent infinite loop
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++) {
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));
placed++;
placedHere = true;
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;
}
}
}