I’ve talked about caves a lot recently so I’m just going to dump a previous post here.
I did some basic terrain generation a while ago using OpenSimplex noise. It turned out pretty good:
The steps went a bit like this:
float hillCoeff = 8f;
float terrainLimit = hillCoeff + (sizey / 8);
int dirtLimit = Math.round(hillCoeff + (sizey / 8));
int caveStart = dirtLimit - (sizey / 32);
// generate the hills
for (int i = 0; i < sizex; i++) {
float noise = (float) noiseGen.eval(i * 0.15f, -1 * 0.15f);
int actualHeight = Math.round(noise * hillCoeff);
int topOfDirt = actualHeight + (sizey / 16);
int endOfDirt = actualHeight + (sizey / 8);
for (int y = endOfDirt; y >= topOfDirt; y--) {
setBlock(Blocks.instance().getBlock("dirt"), i, y);
}
setBlock(Blocks.instance().getBlock("grass"), i, actualHeight + (sizey / 16));
for (int y = endOfDirt; y < sizey; y++) {
setBlock(Blocks.instance().getBlock("stone"), i, y);
}
// long cave under surface to cover up noise's abrupt end
for (int y = caveStart - Math.round(4 * noise) - 6; y < caveStart
+ Math.round(3 * noise) + 3; y++) {
setBlock(Blocks.instance().getBlock("empty"), i, y);
}
}
/* NOTES
* Terrain upper limit is essentially 1 * hillCoeff + (sizey / 8)
* dirt ends at around hillCoeff + (sizey / 8)
* noise ends at dirtLimit - (sizey / 32)
* caves start at dirtLimit - (sizey / 32)
*
*/
// generate the caves
float caveStartThreshold = 0.56f;
float caveEndThreshold = 0.825f;
for (int x = 0; x < sizex; x++) {
for (int y = caveStart; y < sizey; y++) {
float noise = (float) noiseGen.eval(x * 0.1f, y * 0.1f);
noise = (noise + 1) / 2f;
if (noise >= caveStartThreshold && noise <= caveEndThreshold) {
setBlock(Blocks.instance().getBlock("empty"), x, y);
}
}
}
Github code here.
The code generated the hills using 1D noise (that’s actually 2D, but the Y dimension is always -1), and added a cave at the bottom that’s a bit like the inverse of the hill heights. This is to cover up the cave generation stub.
Caves are generated with 2D noise and a min-max value. If the noise function returns a value (which is changed to 0-1 for ease) that is between the min and max it will set the block to air. Likewise, you could do the same thing except for ore deposits or different types of stone, etc. before cave generation.
I hope that helps! If you need me to explain more I can!