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
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
|
|
}
|