@threedog/terrain-noise 0.7.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 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 `plain` 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.
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.7
6
+ npm install @threedog/terrain-noise@0.8
7
7
  ```
8
8
 
9
- This describes 0.7.0: `npm install @threedog/terrain-noise@0.7` (games made in the [repository](https://github.com/penstic123-code/ThreeDog.js-Game-Engine) already have it).
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
- /** Overall relief multiplier */
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, plain), rivers, biomes.
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
@@ -7,6 +7,7 @@
7
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, // overall relief multiplier
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 * 0.0022 + 40, z * 0.0022 - 70, 3) - 0.5), w = P.riverWidth, bank = w * 2.2;
70
- if (r < bank) h = h + (n.waterLevel - 1.6 - h) * Math.min(1, smooth(1 - r / bank) * (r < w ? 1 : 0.85) * 1.25);
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 * 0.0022 + 40, z * 0.0022 - 70, 3) - 0.5), w = P.riverWidth, bank = w * 2.2, t = 1 - r / bank;
84
- return r >= bank ? 0 : t * t * (3 - 2 * t) * (r < w ? 1 : 0.85);
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 * 0.0022 + 40, z * 0.0022 - 70, 3) - 0.5), w = P.riverWidth, bank = w * 2.2, t = 1 - r / bank;
106
- return r >= bank ? 0 : t * t * (3 - 2 * t) * (r < w ? 1 : 0.85);
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 and
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.7.0",
4
- "description": "Optional terrain generator for threedog: noise hills, island, canyon or plain shapes, rivers and a biome rule table (world shape only, no colors)",
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/ThreeDog.js-Game-Engine.git",
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/ThreeDog.js-Game-Engine#readme",
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.7.0"
30
+ "threedog": "^0.8.0"
31
31
  }
32
32
  }