You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

53 lines
1.7 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(noise2D: NoiseFunction2D) {
const rand: NoiseFunction2D = (x, y) => 0.5 + 0.5 * noise2D(x, y)
// randomly generate a block
// level: number, smaller is "higher"
// column: number, the x-axis
// before: Block, the block type left of (before) this block
// above: Block, the block type above this block
const generateBlock = (level: number, column: number, before: Block, above: Block): 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.treeTopMiddle
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[], previousRow: Block[]) => {
for (let i = 0; i < row.length; i++) {
row[i] = generateBlock(level, column + i, row[i - 1], previousRow[i])
}
}
return fillRow
}