48 lines
1.4 KiB
TypeScript
48 lines
1.4 KiB
TypeScript
import type { NoiseFunction2D } from 'simplex-noise'
|
|
import {blockTypes as T, level as L, probability as P, type Block} from './def'
|
|
|
|
export default function createBlockGenerator(rand: NoiseFunction2D) {
|
|
// randomly generate a block
|
|
// level: number, smaller is "higher"
|
|
// column: number, the x-axis
|
|
const generateBlock = (level: number, column: number): Block => {
|
|
// no randomness needed, there is always air above the trees
|
|
if (level < L.treeTop) return T.air
|
|
|
|
const r = rand(level, column)
|
|
|
|
// Air layer: mostly air, sometimes trees
|
|
if (level < L.ground) {
|
|
if (level === L.treeTop && r < P.tree) return T.treeCrown
|
|
return T.air
|
|
}
|
|
|
|
// Soil layer: Mostly soil, sometimes gravel
|
|
if (level < L.rock) {
|
|
if (r < P.soilGravel) return T.soilGravel
|
|
else return T.soil
|
|
}
|
|
|
|
// Rock level: Mostly stone, sometimes gravel
|
|
if (level < L.underground) {
|
|
if (r < P.stoneGravel) return T.stoneGravel
|
|
else return T.stone
|
|
}
|
|
|
|
// Underground: Mostly bedrock, sometimes caves
|
|
// the probability for a cave rises with the level
|
|
const a = P.cave / L.caveMax**2
|
|
const p = Math.min(P.cave, a * level**2)
|
|
|
|
if (r < p) return T.cave
|
|
return T.bedrock
|
|
}
|
|
|
|
const fillRow = (level: number, column: number, row: Block[]) => {
|
|
for (let i = 0; i < row.length; i++) {
|
|
row[i] = generateBlock(level, column + i)
|
|
}
|
|
}
|
|
|
|
return { fillRow, generateBlock }
|
|
}
|