@threedog/terrain-noise 0.5.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/index.d.ts +6 -2
- package/index.js +13 -11
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# @threedog/terrain-noise
|
|
2
2
|
|
|
3
|
-
Optional terrain generator for [threedog](https://www.npmjs.com/package/threedog): noise hills, `island`, `canyon` or `
|
|
3
|
+
Optional terrain generator for [threedog](https://www.npmjs.com/package/threedog): noise hills, `island`, `canyon` or `flat` shapes, rivers and a biome rule table. It decides the shape of the world only; ground colors belong to the game's style (keyed by the biome names). Without it the engine's ground is flat.
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
|
-
npm install @threedog/terrain-noise@0.
|
|
6
|
+
npm install @threedog/terrain-noise@0.8
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
This describes 0.
|
|
9
|
+
This describes 0.8.0: `npm install @threedog/terrain-noise@0.8` (games made in the [repository](https://github.com/penstic123-code/Threedog.js-Game-Engine) already have it).
|
|
10
10
|
|
|
11
11
|
```js
|
|
12
12
|
import { openWorld } from 'threedog';
|
package/index.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export interface BiomeRule extends BiomeCondition { name: string; any?: BiomeCon
|
|
|
21
21
|
export interface TerrainPresetOptions {
|
|
22
22
|
/** Landform, default 'hills' */
|
|
23
23
|
shape?: 'hills' | 'island' | 'canyon' | 'flat';
|
|
24
|
-
/**
|
|
24
|
+
/** Multiplies the base land and hills around sea level (lows get deeper as highs rise); the mountain part (`mountains`) is separate and not scaled by it */
|
|
25
25
|
heightScale?: number;
|
|
26
26
|
/** Mountain strength */
|
|
27
27
|
mountains?: number;
|
|
@@ -29,6 +29,8 @@ export interface TerrainPresetOptions {
|
|
|
29
29
|
rivers?: boolean;
|
|
30
30
|
/** River width (0.02 narrow, 0.05 wide) */
|
|
31
31
|
riverWidth?: number;
|
|
32
|
+
/** Where rivers run and how their banks fall: noise scale and offset, bank width in river widths, the depth share outside the river itself */
|
|
33
|
+
river?: { scale?: number; offset?: number[]; bank?: number; edge?: number };
|
|
32
34
|
/** Biome rule table (default BIOMES) */
|
|
33
35
|
biomes?: BiomeRule[];
|
|
34
36
|
tempScale?: number; moistScale?: number;
|
|
@@ -41,13 +43,15 @@ export interface TerrainPresetOptions {
|
|
|
41
43
|
/** The default biome rule table: beach, snow, rock, riverbank, wetland, savanna, forest, highland, meadow */
|
|
42
44
|
export const BIOMES: BiomeRule[];
|
|
43
45
|
/**
|
|
44
|
-
* Noise terrain generator for terrain() / openWorld({ terrain }) / createTerrain(): noise hills (or island, canyon,
|
|
46
|
+
* Noise terrain generator for terrain() / openWorld({ terrain }) / createTerrain(): noise hills (or island, canyon, flat), rivers, biomes.
|
|
45
47
|
* @example engine.use(openWorld({ seed: 7, camera: 'follow', terrain: terrainPreset({ shape: 'island' }) }))
|
|
46
48
|
*/
|
|
47
49
|
export function terrainPreset(opts?: TerrainPresetOptions): {
|
|
48
50
|
height: (x: number, z: number, n: TerrainNoise) => number;
|
|
49
51
|
groundType: (x: number, z: number, h: number, slope: number, n: TerrainNoise) => string;
|
|
50
52
|
params: Record<string, any>;
|
|
53
|
+
/** Sea level this generator carves rivers and coasts toward */
|
|
54
|
+
waterLevel: number;
|
|
51
55
|
};
|
|
52
56
|
/** Display names of the preset's ground types ('ground.<type>' keys in zh-CN and en): engine.i18n.add(terrainStrings) */
|
|
53
57
|
export const terrainStrings: Record<string, Record<string, string>>;
|
package/index.js
CHANGED
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
// import { terrainPreset } from '@threedog/terrain-noise';
|
|
5
5
|
// engine.use(openWorld({ seed: 7, camera: 'follow', terrain: terrainPreset({ shape: 'island' }) }));
|
|
6
6
|
// Why its own package and not part of a style: the shape of the world (where hills, rivers and forests are) is gameplay, and a style
|
|
7
|
-
// pack holds looks only (packages/engine/docs/recipes/09-
|
|
7
|
+
// pack holds looks only (packages/engine/docs/recipes/09-materials-lights-models.md). Swapping the picture must never move a river. The colors of these ground types belong
|
|
8
8
|
// to whichever style the game uses (e.g. style.terrain.biomeColors, keyed by the names below).
|
|
9
9
|
// height and groundType run in terrain workers, so they are pure: they read only their parameters (n.params is the options below) and Math.
|
|
10
|
+
// That is also why the river formula is written out in each of them (core/threads/threadPure.js recompiles a function in an empty scope, so a shared helper is out of reach): the numbers live once, in `river`.
|
|
10
11
|
// The ground type names are plain strings that vegetation rules, style colors and a game's footstep map match by name.
|
|
11
12
|
|
|
12
13
|
// Biome rules: checked top to bottom, the first match is the biome there (the last has no condition and is the default).
|
|
@@ -34,10 +35,11 @@ export const terrainStrings = {
|
|
|
34
35
|
|
|
35
36
|
const DEFAULTS = {
|
|
36
37
|
shape: 'hills', // 'hills' | 'island' | 'canyon' (mesas) | 'flat' (gentle plain)
|
|
37
|
-
heightScale: 1, //
|
|
38
|
+
heightScale: 1, // multiplies the base land and hills around sea level (lows get deeper too, not only highs); `mountains` is a separate amount that heightScale does not scale, so the highest point may not rise with it
|
|
38
39
|
mountains: 1, // mountain strength
|
|
39
40
|
rivers: true, // carve rivers
|
|
40
41
|
riverWidth: 0.03, // river width (noise threshold, 0.02 narrow, 0.05 wide)
|
|
42
|
+
river: { scale: 0.0022, offset: [40, -70], bank: 2.2, edge: 0.85 }, // noise behind the rivers; bank width in river widths; the share of depth outside the river itself
|
|
41
43
|
biomes: BIOMES,
|
|
42
44
|
tempScale: 0.0011, moistScale: 0.0014, tempLapse: 0.006, // temperature / moisture noise scale; temperature drop per meter of altitude
|
|
43
45
|
noise: { baseScale: 0.0035, baseAmp: 46, hillScale: 0.016, hillAmp: 10, mountainScale: 0.0018, mountainAmp: 900, mountainThreshold: 0.52, seaBias: 0.42 },
|
|
@@ -66,8 +68,8 @@ function height(x, z, n) {
|
|
|
66
68
|
} else h = hills();
|
|
67
69
|
// rivers: thin bands where noise is near 0.5 are dug below the water surface
|
|
68
70
|
if (P.rivers) {
|
|
69
|
-
const r = Math.abs(fbm(x *
|
|
70
|
-
if (r < bank) h = h + (n.waterLevel - 1.6 - h) * Math.min(1, smooth(1 - r / bank) * (r < w ? 1 :
|
|
71
|
+
const R = P.river, r = Math.abs(fbm(x * R.scale + R.offset[0], z * R.scale + R.offset[1], 3) - 0.5), w = P.riverWidth, bank = w * R.bank;
|
|
72
|
+
if (r < bank) h = h + (n.waterLevel - 1.6 - h) * Math.min(1, smooth(1 - r / bank) * (r < w ? 1 : R.edge) * 1.25);
|
|
71
73
|
}
|
|
72
74
|
return h;
|
|
73
75
|
}
|
|
@@ -80,8 +82,8 @@ function groundType(x, z, h, sl, n) {
|
|
|
80
82
|
const moist = () => ms ??= fbm(x * P.moistScale - 200, z * P.moistScale + 100, 3);
|
|
81
83
|
const river = () => rv ??= (() => {
|
|
82
84
|
if (!P.rivers) return 0;
|
|
83
|
-
const r = Math.abs(fbm(x *
|
|
84
|
-
return r >= bank ? 0 : t * t * (3 - 2 * t) * (r < w ? 1 :
|
|
85
|
+
const R = P.river, r = Math.abs(fbm(x * R.scale + R.offset[0], z * R.scale + R.offset[1], 3) - 0.5), w = P.riverWidth, bank = w * R.bank, t = 1 - r / bank;
|
|
86
|
+
return r >= bank ? 0 : t * t * (3 - 2 * t) * (r < w ? 1 : R.edge);
|
|
85
87
|
})();
|
|
86
88
|
const test = c => c.any ? c.any.some(test) : !((c.minHeight != null && h < c.minHeight) || (c.maxHeight != null && h > c.maxHeight) ||
|
|
87
89
|
(c.maxAboveWater != null && h >= W + c.maxAboveWater) || (c.minSlope != null && sl < c.minSlope) ||
|
|
@@ -102,18 +104,18 @@ function groundType(x, z, h, sl, n) {
|
|
|
102
104
|
export function riverAt(x, z, n) {
|
|
103
105
|
const P = n.params;
|
|
104
106
|
if (!P?.rivers) return 0;
|
|
105
|
-
const r = Math.abs(n.fbm(x *
|
|
106
|
-
return r >= bank ? 0 : t * t * (3 - 2 * t) * (r < w ? 1 :
|
|
107
|
+
const R = P.river, r = Math.abs(n.fbm(x * R.scale + R.offset[0], z * R.scale + R.offset[1], 3) - 0.5), w = P.riverWidth, bank = w * R.bank, t = 1 - r / bank;
|
|
108
|
+
return r >= bank ? 0 : t * t * (3 - 2 * t) * (r < w ? 1 : R.edge);
|
|
107
109
|
}
|
|
108
110
|
|
|
109
111
|
/**
|
|
110
|
-
* Noise terrain preset: spread it into terrain() (or openWorld({ terrain })). Options override the defaults above; noise, island
|
|
111
|
-
* canyon merge field by field.
|
|
112
|
+
* Noise terrain preset: spread it into terrain() (or openWorld({ terrain })). Options override the defaults above; noise, island,
|
|
113
|
+
* canyon and river merge field by field.
|
|
112
114
|
* @example engine.use(terrain({ seed: 7, ...terrainPreset({ shape: 'island', rivers: false }) }))
|
|
113
115
|
* @param {Partial<typeof DEFAULTS>} [opts]
|
|
114
116
|
*/
|
|
115
117
|
export function terrainPreset(opts = {}) {
|
|
116
118
|
const params = { ...DEFAULTS, ...opts };
|
|
117
|
-
for (const k of ['noise', 'island', 'canyon']) params[k] = { ...DEFAULTS[k], ...(opts[k] || {}) };
|
|
119
|
+
for (const k of ['noise', 'island', 'canyon', 'river']) params[k] = { ...DEFAULTS[k], ...(opts[k] || {}) };
|
|
118
120
|
return { waterLevel: 0, height, groundType, params }; // this generator's rivers and coasts are carved toward sea level 0
|
|
119
121
|
}
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@threedog/terrain-noise",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Optional terrain generator for threedog: noise hills, island, canyon or
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"description": "Optional terrain generator for threedog: noise hills, island, canyon or flat shapes, rivers and a biome rule table (world shape only, no colors)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/penstic123-code/
|
|
8
|
+
"url": "git+https://github.com/penstic123-code/Threedog.js-Game-Engine.git",
|
|
9
9
|
"directory": "packages/terrain-noise"
|
|
10
10
|
},
|
|
11
|
-
"homepage": "https://github.com/penstic123-code/
|
|
11
|
+
"homepage": "https://github.com/penstic123-code/Threedog.js-Game-Engine#readme",
|
|
12
12
|
"type": "module",
|
|
13
13
|
"engines": {
|
|
14
14
|
"node": "^20.19.0 || >=22.12.0"
|
|
@@ -27,6 +27,6 @@
|
|
|
27
27
|
"*.d.ts"
|
|
28
28
|
],
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"threedog": "^0.
|
|
30
|
+
"threedog": "^0.8.0"
|
|
31
31
|
}
|
|
32
32
|
}
|