@v12-engine/create 0.1.1 → 0.4.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 +4 -1
- package/base/_gitignore +5 -0
- package/base/package.json +3 -3
- package/base/src/main.ts +36 -10
- package/base/src/navigation.worker.ts +7 -0
- package/base/vite.config.ts +24 -2
- package/cli.mjs +21 -6
- package/index.mjs +27 -7
- package/layers/desktop/electron/app.mjs +237 -0
- package/layers/desktop/electron/config.mjs +16 -0
- package/layers/desktop/electron/dev.mjs +63 -0
- package/layers/desktop/electron/files.mjs +86 -0
- package/layers/desktop/electron/icons/icon.icns +0 -0
- package/layers/desktop/electron/icons/icon.png +0 -0
- package/layers/desktop/electron/main.mjs +12 -0
- package/layers/desktop/electron/package.mjs +75 -0
- package/layers/desktop/electron/preload.cjs +41 -0
- package/layers/desktop/electron/presentation.m +87 -0
- package/layers/desktop/electron/serve.mjs +76 -0
- package/layers/desktop/electron/tools.mjs +63 -0
- package/layers/desktop/electron/updates.mjs +71 -0
- package/layers/desktop/package.json +13 -0
- package/layers/desktop/src/desktop.ts +175 -0
- package/layers/desktop/src/shell.ts +279 -0
- package/layers/desktop/tests/main.test.ts +189 -0
- package/layers/desktop/tests/shell.test.ts +152 -0
- package/layers/rooms/server.ts +13 -10
- package/layers/server/server.ts +4 -5
- package/layers/source/vite.config.ts +21 -1
- package/package.json +1 -1
- package/starters/campaign/README.md +9 -2
- package/starters/campaign/layers/rooms/server.ts +3 -3
- package/starters/campaign/layers/server/server.ts +3 -5
- package/starters/campaign/layers/tests/tests/rules.test.ts +40 -21
- package/starters/campaign/src/campaign/game.ts +26 -5
- package/starters/campaign/src/campaign/index.ts +104 -68
- package/starters/campaign/src/campaign/kills.ts +1 -1
- package/starters/campaign/src/campaign/missions/homecoming.ts +7 -7
- package/starters/campaign/src/campaign/missions/siege.ts +6 -6
- package/starters/campaign/src/campaign/missions/warlord.ts +13 -14
- package/starters/campaign/src/campaign/scenes.ts +8 -7
- package/starters/campaign/src/campaign/units.ts +59 -20
- package/starters/campaign/src/campaign/view/attacks.ts +19 -0
- package/starters/campaign/src/campaign/view/fire.ts +2 -2
- package/starters/campaign/src/campaign/view/index.ts +54 -43
- package/starters/campaign/src/campaign/waves.ts +18 -17
- package/starters/campaign/src/game.ts +8 -1
- package/starters/campaign/src/main.ts +38 -19
- package/starters/campaign/src/maps/fort.names.ts +2 -2
- package/starters/campaign/src/maps/fort.vgmap.json +102 -2
- package/starters/campaign/src/maps/homestead.names.ts +2 -2
- package/starters/campaign/src/maps/homestead.vgmap.json +85 -1
- package/starters/campaign/src/maps/pass.names.ts +2 -2
- package/starters/campaign/src/maps/pass.vgmap.json +69 -1
- package/starters/campaign/src/waves-panel.ts +2 -1
- package/starters/empty/README.md +18 -10
- package/starters/empty/layers/tests/tests/rules.test.ts +16 -17
- package/starters/empty/src/game.ts +11 -75
- package/starters/empty/src/generate.worker.ts +5 -5
- package/starters/empty/src/rules.ts +83 -25
- package/starters/empty/src/view.ts +82 -0
- package/starters/examples/README.md +83 -0
- package/starters/examples/layers/tests/tests/examples.test.ts +30 -0
- package/starters/examples/package.json +5 -0
- package/starters/examples/src/examples/abilities/areas.ts +165 -0
- package/starters/examples/src/examples/abilities/areasLooks.ts +30 -0
- package/starters/examples/src/examples/abilities/buffs.ts +287 -0
- package/starters/examples/src/examples/abilities/buffsLooks.ts +46 -0
- package/starters/examples/src/examples/abilities/changing.ts +228 -0
- package/starters/examples/src/examples/abilities/changingLooks.ts +61 -0
- package/starters/examples/src/examples/abilities/control.ts +158 -0
- package/starters/examples/src/examples/abilities/controlLooks.ts +78 -0
- package/starters/examples/src/examples/abilities/damage.ts +156 -0
- package/starters/examples/src/examples/abilities/damageLooks.ts +37 -0
- package/starters/examples/src/examples/abilities/family.ts +29 -0
- package/starters/examples/src/examples/abilities/index.ts +32 -0
- package/starters/examples/src/examples/abilities/kit.ts +179 -0
- package/starters/examples/src/examples/abilities/lookKit.ts +71 -0
- package/starters/examples/src/examples/abilities/looks.ts +47 -0
- package/starters/examples/src/examples/abilities/missiles.ts +203 -0
- package/starters/examples/src/examples/abilities/missilesLooks.ts +38 -0
- package/starters/examples/src/examples/abilities/moves.ts +206 -0
- package/starters/examples/src/examples/abilities/movesLooks.ts +52 -0
- package/starters/examples/src/examples/abilities/recasts.ts +181 -0
- package/starters/examples/src/examples/abilities/recastsLooks.ts +41 -0
- package/starters/examples/src/examples/abilities/resources.ts +166 -0
- package/starters/examples/src/examples/abilities/resourcesLooks.ts +42 -0
- package/starters/examples/src/examples/abilities/summons.ts +296 -0
- package/starters/examples/src/examples/abilities/summonsLooks.ts +115 -0
- package/starters/examples/src/examples/abilities/triggers.ts +204 -0
- package/starters/examples/src/examples/abilities/triggersLooks.ts +53 -0
- package/starters/examples/src/examples/abilities/vision.ts +137 -0
- package/starters/examples/src/examples/abilities/visionLooks.ts +50 -0
- package/starters/examples/src/examples/animation/index.ts +235 -0
- package/starters/examples/src/examples/animation/looks.ts +444 -0
- package/starters/examples/src/examples/catalog.ts +52 -0
- package/starters/examples/src/examples/cinematics/index.ts +217 -0
- package/starters/examples/src/examples/cinematics/looks.ts +476 -0
- package/starters/examples/src/examples/cinematics/tour.json +43 -0
- package/starters/examples/src/examples/cinematics/village.ts +88 -0
- package/starters/examples/src/examples/common/looks.ts +65 -0
- package/starters/examples/src/examples/common/units.ts +70 -0
- package/starters/examples/src/examples/construction/index.ts +329 -0
- package/starters/examples/src/examples/construction/looks.ts +275 -0
- package/starters/examples/src/examples/custom-animation/bones.ts +92 -0
- package/starters/examples/src/examples/custom-animation/index.ts +190 -0
- package/starters/examples/src/examples/custom-animation/looks.ts +523 -0
- package/starters/examples/src/examples/custom-animation/runes.ts +82 -0
- package/starters/examples/src/examples/custom-fx/glaive.look.ts +110 -0
- package/starters/examples/src/examples/custom-fx/glaive.ts +40 -0
- package/starters/examples/src/examples/custom-fx/gpu.look.ts +145 -0
- package/starters/examples/src/examples/custom-fx/gpu.ts +22 -0
- package/starters/examples/src/examples/custom-fx/index.ts +25 -0
- package/starters/examples/src/examples/custom-fx/lights.look.ts +144 -0
- package/starters/examples/src/examples/custom-fx/lights.ts +25 -0
- package/starters/examples/src/examples/custom-fx/looks.ts +36 -0
- package/starters/examples/src/examples/custom-fx/meteor.look.ts +133 -0
- package/starters/examples/src/examples/custom-fx/meteor.ts +26 -0
- package/starters/examples/src/examples/custom-fx/parts.look.ts +193 -0
- package/starters/examples/src/examples/custom-fx/parts.ts +21 -0
- package/starters/examples/src/examples/custom-fx/portal.look.ts +193 -0
- package/starters/examples/src/examples/custom-fx/portal.ts +48 -0
- package/starters/examples/src/examples/custom-fx/renderer.look.ts +139 -0
- package/starters/examples/src/examples/custom-fx/renderer.ts +18 -0
- package/starters/examples/src/examples/custom-fx/ribbons.look.ts +151 -0
- package/starters/examples/src/examples/custom-fx/ribbons.ts +22 -0
- package/starters/examples/src/examples/custom-fx/shader.ts +42 -0
- package/starters/examples/src/examples/custom-fx/shield.look.ts +226 -0
- package/starters/examples/src/examples/custom-fx/shield.ts +43 -0
- package/starters/examples/src/examples/define.ts +86 -0
- package/starters/examples/src/examples/destruction/index.ts +570 -0
- package/starters/examples/src/examples/destruction/looks.ts +447 -0
- package/starters/examples/src/examples/dialogs/index.ts +383 -0
- package/starters/examples/src/examples/dialogs/looks.ts +546 -0
- package/starters/examples/src/examples/dynamic-map/index.ts +603 -0
- package/starters/examples/src/examples/dynamic-map/looks.ts +301 -0
- package/starters/examples/src/examples/fx/blood.look.ts +62 -0
- package/starters/examples/src/examples/fx/blood.ts +59 -0
- package/starters/examples/src/examples/fx/feel.look.ts +86 -0
- package/starters/examples/src/examples/fx/feel.ts +57 -0
- package/starters/examples/src/examples/fx/fight.ts +28 -0
- package/starters/examples/src/examples/fx/floats.look.ts +108 -0
- package/starters/examples/src/examples/fx/floats.ts +24 -0
- package/starters/examples/src/examples/fx/gallery.look.ts +168 -0
- package/starters/examples/src/examples/fx/gallery.ts +23 -0
- package/starters/examples/src/examples/fx/index.ts +30 -0
- package/starters/examples/src/examples/fx/links.look.ts +83 -0
- package/starters/examples/src/examples/fx/links.ts +49 -0
- package/starters/examples/src/examples/fx/looks.ts +55 -0
- package/starters/examples/src/examples/fx/map.look.ts +93 -0
- package/starters/examples/src/examples/fx/map.ts +33 -0
- package/starters/examples/src/examples/fx/marks.look.ts +100 -0
- package/starters/examples/src/examples/fx/marks.ts +36 -0
- package/starters/examples/src/examples/fx/shots.look.ts +92 -0
- package/starters/examples/src/examples/fx/shots.ts +71 -0
- package/starters/examples/src/examples/fx/spells.look.ts +87 -0
- package/starters/examples/src/examples/fx/spells.ts +122 -0
- package/starters/examples/src/examples/fx/stage.ts +31 -0
- package/starters/examples/src/examples/gui/babylonScreen.ts +167 -0
- package/starters/examples/src/examples/gui/babylonWorld.ts +191 -0
- package/starters/examples/src/examples/gui/htmlPart.ts +95 -0
- package/starters/examples/src/examples/gui/index.ts +143 -0
- package/starters/examples/src/examples/gui/keys.ts +91 -0
- package/starters/examples/src/examples/gui/layout.ts +42 -0
- package/starters/examples/src/examples/gui/looks.ts +270 -0
- package/starters/examples/src/examples/gui/minimap.ts +127 -0
- package/starters/examples/src/examples/gui/ownInterface.ts +129 -0
- package/starters/examples/src/examples/gui/plates.ts +87 -0
- package/starters/examples/src/examples/gui/radial.ts +104 -0
- package/starters/examples/src/examples/gui/solidPart.ts +107 -0
- package/starters/examples/src/examples/looks.ts +45 -0
- package/starters/examples/src/examples/mechanics/battle.ts +51 -0
- package/starters/examples/src/examples/mechanics/damage.ts +80 -0
- package/starters/examples/src/examples/mechanics/flying.ts +93 -0
- package/starters/examples/src/examples/mechanics/formations.ts +58 -0
- package/starters/examples/src/examples/mechanics/highGround.ts +82 -0
- package/starters/examples/src/examples/mechanics/index.ts +44 -0
- package/starters/examples/src/examples/mechanics/looks.ts +289 -0
- package/starters/examples/src/examples/mechanics/maze.ts +119 -0
- package/starters/examples/src/examples/mechanics/orders.ts +68 -0
- package/starters/examples/src/examples/mechanics/selection.ts +30 -0
- package/starters/examples/src/examples/moba/index.ts +377 -0
- package/starters/examples/src/examples/moba/looks.ts +349 -0
- package/starters/examples/src/examples/moba/maps.ts +69 -0
- package/starters/examples/src/examples/moba/spells.ts +34 -0
- package/starters/examples/src/examples/moba/units.ts +196 -0
- package/starters/examples/src/examples/nature/camera.ts +15 -0
- package/starters/examples/src/examples/nature/grass.ts +64 -0
- package/starters/examples/src/examples/nature/index.ts +327 -0
- package/starters/examples/src/examples/nature/land.ts +173 -0
- package/starters/examples/src/examples/nature/looks.ts +577 -0
- package/starters/examples/src/examples/nature/maps.ts +370 -0
- package/starters/examples/src/examples/nature/skies.ts +324 -0
- package/starters/examples/src/examples/nature/weather.ts +80 -0
- package/starters/examples/src/examples/performance/index.ts +263 -0
- package/starters/examples/src/examples/performance/looks.ts +372 -0
- package/starters/examples/src/examples/performance/meter.ts +158 -0
- package/starters/examples/src/examples/post/grades.ts +86 -0
- package/starters/examples/src/examples/post/index.ts +202 -0
- package/starters/examples/src/examples/post/looks.ts +884 -0
- package/starters/examples/src/examples/post/passes.ts +213 -0
- package/starters/examples/src/examples/rts/ai.ts +49 -0
- package/starters/examples/src/examples/rts/airlift.ts +43 -0
- package/starters/examples/src/examples/rts/base.ts +129 -0
- package/starters/examples/src/examples/rts/build.ts +65 -0
- package/starters/examples/src/examples/rts/camps.ts +36 -0
- package/starters/examples/src/examples/rts/carry.ts +103 -0
- package/starters/examples/src/examples/rts/creeps.ts +61 -0
- package/starters/examples/src/examples/rts/data.ts +406 -0
- package/starters/examples/src/examples/rts/ferry.ts +41 -0
- package/starters/examples/src/examples/rts/garrison.ts +50 -0
- package/starters/examples/src/examples/rts/harvest.ts +29 -0
- package/starters/examples/src/examples/rts/hero.ts +67 -0
- package/starters/examples/src/examples/rts/index.ts +77 -0
- package/starters/examples/src/examples/rts/looks.ts +721 -0
- package/starters/examples/src/examples/rts/shop.ts +46 -0
- package/starters/examples/src/examples/rts/tech.ts +39 -0
- package/starters/examples/src/examples/rts/train.ts +48 -0
- package/starters/examples/src/examples/rts/waterside.ts +185 -0
- package/starters/examples/src/examples/showcase/index.ts +714 -0
- package/starters/examples/src/examples/showcase/looks.ts +238 -0
- package/starters/examples/src/game.ts +17 -0
- package/starters/examples/src/main.ts +82 -0
- package/starters/examples/src/rules.ts +31 -0
- package/starters/examples/src/shell/look.ts +79 -0
- package/starters/examples/src/shell/registry.ts +7 -0
- package/starters/examples/src/shell/scenes.ts +178 -0
- package/starters/examples/src/shell/shell.ts +290 -0
- package/starters/examples/src/shell/style.ts +202 -0
- package/starters/examples/src/view.ts +50 -0
- package/starters/melee/README.md +12 -3
- package/starters/melee/layers/tests/tests/heroes.test.ts +402 -0
- package/starters/melee/layers/tests/tests/rules.test.ts +10 -8
- package/starters/melee/src/game.ts +32 -2
- package/starters/melee/src/maps/bay.names.ts +2 -2
- package/starters/melee/src/maps/bay.vgmap.json +198 -1
- package/starters/melee/src/maps.ts +11 -9
- package/starters/melee/src/melee/abilities.ts +1 -194
- package/starters/melee/src/melee/blight.ts +7 -7
- package/starters/melee/src/melee/cellLayers.json +3 -3
- package/starters/melee/src/melee/data.json +1 -18
- package/starters/melee/src/melee/game.ts +6 -4
- package/starters/melee/src/melee/heroes.ts +1025 -0
- package/starters/melee/src/melee/index.ts +64 -61
- package/starters/melee/src/melee/items.ts +15 -362
- package/starters/melee/src/melee/languages/he.json +14 -2
- package/starters/melee/src/melee/pings.ts +5 -6
- package/starters/melee/src/melee/saves.ts +1 -1
- package/starters/melee/src/melee/undead.ts +15 -230
- package/starters/melee/src/melee/units.ts +37 -171
- package/starters/melee/src/melee/view/attacks.ts +19 -0
- package/starters/melee/src/melee/view/heroSpellLooks.ts +39 -8
- package/starters/melee/src/melee/view/index.ts +56 -52
- package/starters/melee/src/melee/view/looks.ts +86 -63
- package/starters/melee/src/melee/view/undeadLooks.ts +70 -31
- package/starters/melee/src/melee/view/walls.ts +1 -1
- package/starters.mjs +6 -0
- package/v12.mjs +14 -15
- package/starters/campaign/src/rules.ts +0 -20
- package/starters/empty/src/maps.ts +0 -44
- package/starters/empty/src/tiles.ts +0 -12
- package/starters/melee/src/melee/heroSpells.ts +0 -38
- package/starters/melee/src/rules.ts +0 -24
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The nature examples' maps, each made in code (`./land.ts`): a forest round a glade, a meadow of every style of grass,
|
|
3
|
+
* a lake under a waterfall, rolling hills, a misty valley, a village, and a dry field by a wood. Where each puts its
|
|
4
|
+
* trees, worked out from the map so that a command can plant them again where they stood
|
|
5
|
+
*/
|
|
6
|
+
import { exactMath } from '@v12-engine/engine'
|
|
7
|
+
import type { GameMap } from '@v12-engine/engine'
|
|
8
|
+
|
|
9
|
+
type Rgb = [number, number, number]
|
|
10
|
+
import { STYLE } from './grass'
|
|
11
|
+
import { type At, band, blob, distanceToLine, field, grow, mow, noise, paint, place, pour, raise, scatter, sculpt, smooth } from './land'
|
|
12
|
+
|
|
13
|
+
/** Ground that rolls a little, `amount` high: the field's 1 as its middle */
|
|
14
|
+
const rolling =
|
|
15
|
+
(amount: number, scale = 14, seed = 3) =>
|
|
16
|
+
(x: number, z: number) =>
|
|
17
|
+
1 + (noise(x, z, scale, seed) - 0.5) * 2 * amount
|
|
18
|
+
|
|
19
|
+
// ---- a forest round a glade
|
|
20
|
+
|
|
21
|
+
/** The glade in the forest's middle, and the path that leads into it from the south */
|
|
22
|
+
export const GLADE: At = { x: 32, z: 32 }
|
|
23
|
+
const FOREST_PATH: At[] = [
|
|
24
|
+
{ x: 30, z: 64 },
|
|
25
|
+
{ x: 33, z: 52 },
|
|
26
|
+
{ x: 30, z: 42 },
|
|
27
|
+
{ x: 32, z: 33 }
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
/** A forest of 64 cells a side round a glade of meadow and flowers, a path winding in from the south */
|
|
31
|
+
export function forestMap(): GameMap {
|
|
32
|
+
const map = field('Forest', 64)
|
|
33
|
+
sculpt(map, rolling(0.8, 16))
|
|
34
|
+
const glade = blob(GLADE, 10, 2.5, 4)
|
|
35
|
+
const path = band(FOREST_PATH, 2.2, 0.4)
|
|
36
|
+
paint(map, 'darkGrass', (x, z) => !glade(x, z))
|
|
37
|
+
paint(map, 'dirt', (x, z) => !glade(x, z) && noise(x, z, 5, 9) > 0.68)
|
|
38
|
+
paint(map, 'grass', glade)
|
|
39
|
+
grow(map, STYLE.meadow, glade)
|
|
40
|
+
grow(map, STYLE.flowers, (x, z) => glade(x, z) && noise(x, z, 4, 12) > 0.6)
|
|
41
|
+
grow(map, STYLE.tallGrass, (x, z) => !glade(x, z) && noise(x, z, 7, 13) > 0.62)
|
|
42
|
+
grow(map, STYLE.thicket, (x, z) => blob(GLADE, 12.5, 1.5, 4)(x, z) && !glade(x, z) && noise(x, z, 3, 14) > 0.5)
|
|
43
|
+
paint(map, 'dirt', path)
|
|
44
|
+
mow(map, path)
|
|
45
|
+
for (const [i, at] of [
|
|
46
|
+
{ x: 27, z: 29 },
|
|
47
|
+
{ x: 37, z: 35 },
|
|
48
|
+
{ x: 35, z: 27 }
|
|
49
|
+
].entries())
|
|
50
|
+
place(map, `forest/rock_medium_${i + 1}.glb`, at, { yaw: i * 2.1, scale: 0.9 })
|
|
51
|
+
return map
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Where the forest's trees stand: everywhere but the glade and the path, thicker away from the glade */
|
|
55
|
+
export const forestTrees = (map: GameMap): At[] =>
|
|
56
|
+
scatter(map, (x, z) => !blob(GLADE, 11, 2.5, 4)(x, z) && distanceToLine(FOREST_PATH, x, z) > 2.2 && noise(x, z, 6, 21) > 0.22, 1.7, 11)
|
|
57
|
+
|
|
58
|
+
// ---- a meadow of every style
|
|
59
|
+
|
|
60
|
+
/** The meadow's walkers' two sides: they cross from one to the other through the grass */
|
|
61
|
+
export const MEADOW_WEST = 10
|
|
62
|
+
export const MEADOW_EAST = 46
|
|
63
|
+
|
|
64
|
+
/** A meadow of 56 cells a side, each style of grass in a field of its own, a pond with reeds, trees along its edges */
|
|
65
|
+
export function meadowMap(): GameMap {
|
|
66
|
+
const map = field('Meadow', 56)
|
|
67
|
+
sculpt(map, rolling(0.5, 18))
|
|
68
|
+
const pond = blob({ x: 41, z: 15 }, 4.2, 1, 6)
|
|
69
|
+
pour(map, pond, blob({ x: 41, z: 15 }, 2.8, 0.8, 6))
|
|
70
|
+
paint(map, 'sand', blob({ x: 41, z: 15 }, 5.4, 1, 6))
|
|
71
|
+
grow(map, STYLE.meadow, (x, z) => x > 6 && x < 50 && z > 6 && z < 50)
|
|
72
|
+
// the fields, west to east across the middle where the walkers cross
|
|
73
|
+
grow(map, STYLE.wheat, (x, z) => x > 14 && x < 23 && z > 20 && z < 36 && noise(x, z, 3, 7) > 0.15)
|
|
74
|
+
grow(map, STYLE.tallGrass, blob({ x: 28, z: 28 }, 4.5, 1.2, 7))
|
|
75
|
+
grow(map, STYLE.flowers, blob({ x: 37, z: 31 }, 4, 1.5, 8))
|
|
76
|
+
grow(map, STYLE.dryGrass, blob({ x: 35, z: 42 }, 4.5, 1.5, 9))
|
|
77
|
+
grow(map, STYLE.thicket, blob({ x: 20, z: 43 }, 3, 1, 10))
|
|
78
|
+
grow(map, STYLE.reeds, (x, z) => blob({ x: 41, z: 15 }, 5.6, 1, 6)(x, z) && !blob({ x: 41, z: 15 }, 3.4, 0.8, 6)(x, z))
|
|
79
|
+
mow(map, pond)
|
|
80
|
+
paint(
|
|
81
|
+
map,
|
|
82
|
+
'dirt',
|
|
83
|
+
band(
|
|
84
|
+
[
|
|
85
|
+
{ x: 0, z: 9 },
|
|
86
|
+
{ x: 56, z: 7 }
|
|
87
|
+
],
|
|
88
|
+
1.6
|
|
89
|
+
)
|
|
90
|
+
)
|
|
91
|
+
mow(
|
|
92
|
+
map,
|
|
93
|
+
band(
|
|
94
|
+
[
|
|
95
|
+
{ x: 0, z: 9 },
|
|
96
|
+
{ x: 56, z: 7 }
|
|
97
|
+
],
|
|
98
|
+
1.6
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
return map
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** The meadow's trees: a ring round its edge */
|
|
105
|
+
export const meadowTrees = (map: GameMap): At[] => scatter(map, (x, z) => (x < 6 || x > 50 || z < 5 || z > 50) && noise(x, z, 5, 4) > 0.3, 1.9, 12)
|
|
106
|
+
|
|
107
|
+
// ---- a lake under a waterfall
|
|
108
|
+
|
|
109
|
+
/** The lake's middle, and where the falls come down into it */
|
|
110
|
+
export const LAKE: At = { x: 33, z: 40 }
|
|
111
|
+
export const FALLS: At = { x: 32, z: 22 }
|
|
112
|
+
const UPPER_RIVER: At[] = [
|
|
113
|
+
{ x: 26, z: 0 },
|
|
114
|
+
{ x: 29, z: 8 },
|
|
115
|
+
{ x: 31, z: 15 },
|
|
116
|
+
{ x: 32, z: 22 }
|
|
117
|
+
]
|
|
118
|
+
const LOWER_RIVER: At[] = [
|
|
119
|
+
{ x: 40, z: 44 },
|
|
120
|
+
{ x: 48, z: 47 },
|
|
121
|
+
{ x: 55, z: 45 },
|
|
122
|
+
{ x: 64, z: 49 }
|
|
123
|
+
]
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* A lake of 64 cells a side: a plateau (a cliff level up) across the north with a river on it that spills over the
|
|
127
|
+
* cliff into a pool, a lake below with a sandy shore and reeds, and a river out of it to the east. The waterfalls
|
|
128
|
+
* are found where the water spills from the plateau, by the client (`WaterLook.falls`)
|
|
129
|
+
*/
|
|
130
|
+
export function lakeMap(): GameMap {
|
|
131
|
+
const map = field('Lake', 64)
|
|
132
|
+
sculpt(map, (x, z) => rolling(0.6, 12)(x, z) + smooth(10, 0, z) * 1.5)
|
|
133
|
+
const plateau = (x: number, z: number) => z < 21 + (noise(x, 0, 6, 5) - 0.5) * 3 || (z < 23 && Math.abs(x - FALLS.x) < 4)
|
|
134
|
+
raise(map, 1, plateau)
|
|
135
|
+
const lake = (x: number, z: number) => blob(LAKE, 10, 2, 3)(x, z) || (z >= 21 && z < 32 && Math.abs(x - FALLS.x) < 4.5 + (z - 21) * 0.3)
|
|
136
|
+
const upper = band(UPPER_RIVER, 3.2, 0.3, 4)
|
|
137
|
+
const lower = band(LOWER_RIVER, 2.6, 0.3, 5)
|
|
138
|
+
pour(
|
|
139
|
+
map,
|
|
140
|
+
(x, z) => (plateau(x, z) ? upper(x, z) : lake(x, z) || lower(x, z)),
|
|
141
|
+
(x, z) => (plateau(x, z) ? band(UPPER_RIVER, 1.8)(x, z) : blob(LAKE, 7, 1.5, 3)(x, z))
|
|
142
|
+
)
|
|
143
|
+
paint(map, 'dirt', (x, z) => !plateau(x, z) && blob(LAKE, 12.5, 2, 3)(x, z))
|
|
144
|
+
paint(map, 'sand', (x, z) => !plateau(x, z) && blob(LAKE, 11, 2, 3)(x, z) && noise(x, z, 3, 11) > 0.45)
|
|
145
|
+
paint(map, 'rock', (x, z) => plateau(x, z) && noise(x, z, 4, 8) > 0.6)
|
|
146
|
+
paint(map, 'darkGrass', (x, z) => noise(x, z, 9, 6) > 0.6)
|
|
147
|
+
grow(map, STYLE.meadow, (x, z) => !blob(LAKE, 12.5, 2, 3)(x, z) && noise(x, z, 8, 3) > 0.3)
|
|
148
|
+
grow(map, STYLE.reeds, (x, z) => !plateau(x, z) && blob(LAKE, 12, 2, 3)(x, z) && !blob(LAKE, 10.5, 2, 3)(x, z) && noise(x, z, 3, 2) > 0.45)
|
|
149
|
+
grow(map, STYLE.flowers, (x, z) => noise(x, z, 5, 15) > 0.72)
|
|
150
|
+
mow(map, (x, z) => map.water[Math.floor(z) * map.width + Math.floor(x)] > 0)
|
|
151
|
+
place(map, 'forest/rock_medium_2.glb', { x: 27.5, z: 24 }, { scale: 1.4, yaw: 1 })
|
|
152
|
+
place(map, 'forest/rock_medium_3.glb', { x: 37.5, z: 25 }, { scale: 1.2, yaw: 2.5 })
|
|
153
|
+
place(map, 'village/fantasy_house_2.glb', { x: 48, z: 34 }, { yaw: -2.2, scale: 0.9, blocks: true })
|
|
154
|
+
return map
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** The lake's trees: in woods round it, on the plateau too, never on the shore */
|
|
158
|
+
export const lakeTrees = (map: GameMap): At[] =>
|
|
159
|
+
scatter(
|
|
160
|
+
map,
|
|
161
|
+
(x, z) =>
|
|
162
|
+
!blob(LAKE, 13.5, 2, 3)(x, z) &&
|
|
163
|
+
distanceToLine(UPPER_RIVER, x, z) > 3 &&
|
|
164
|
+
distanceToLine(LOWER_RIVER, x, z) > 3 &&
|
|
165
|
+
exactMath.hypot(x - 48, z - 34) > 4.5 &&
|
|
166
|
+
noise(x, z, 7, 22) > 0.45,
|
|
167
|
+
1.8,
|
|
168
|
+
13
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
// ---- rolling hills, for the clouds
|
|
172
|
+
|
|
173
|
+
/** Hills of 96 cells a side, woods in their hollows: what clouds' shadows are seen running over */
|
|
174
|
+
export function hillsMap(): GameMap {
|
|
175
|
+
const map = field('Hills', 96)
|
|
176
|
+
sculpt(map, (x, z) => 1 + noise(x, z, 22, 2) * 5 + noise(x, z, 7, 3) * 0.8)
|
|
177
|
+
paint(map, 'darkGrass', (x, z) => noise(x, z, 12, 4) > 0.55)
|
|
178
|
+
paint(map, 'rock', (x, z) => noise(x, z, 22, 2) > 0.78)
|
|
179
|
+
grow(map, STYLE.meadow, (x, z) => noise(x, z, 22, 2) < 0.7)
|
|
180
|
+
grow(map, STYLE.flowers, (x, z) => noise(x, z, 6, 9) > 0.75)
|
|
181
|
+
return map
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** The hills' woods */
|
|
185
|
+
export const hillsTrees = (map: GameMap): At[] => scatter(map, (x, z) => noise(x, z, 12, 4) > 0.58, 1.9, 14, 900)
|
|
186
|
+
|
|
187
|
+
// ---- a misty valley
|
|
188
|
+
|
|
189
|
+
/** The line the valley winds along, south to north */
|
|
190
|
+
const VALLEY: At[] = Array.from({ length: 9 }, (_, i) => ({ x: 40 + exactMath.sin(i * 0.9) * 9, z: i * 10 }))
|
|
191
|
+
|
|
192
|
+
/** A valley of 80 cells a side between steep hills, a stream along its floor: the mist lies in it */
|
|
193
|
+
export function valleyMap(): GameMap {
|
|
194
|
+
const map = field('Valley', 80)
|
|
195
|
+
sculpt(map, (x, z) => {
|
|
196
|
+
const away = distanceToLine(VALLEY, x, z)
|
|
197
|
+
return 0.6 + smooth(4, 22, away) * 9 + noise(x, z, 10, 6) * 1.6 * smooth(4, 12, away)
|
|
198
|
+
})
|
|
199
|
+
const stream = band(VALLEY, 2.4, 0.4, 7)
|
|
200
|
+
pour(map, stream, band(VALLEY, 1, 0.2, 7))
|
|
201
|
+
paint(map, 'dirt', (x, z) => distanceToLine(VALLEY, x, z) < 3)
|
|
202
|
+
paint(map, 'darkGrass', (x, z) => distanceToLine(VALLEY, x, z) > 12)
|
|
203
|
+
paint(map, 'rock', (x, z) => distanceToLine(VALLEY, x, z) > 9 && distanceToLine(VALLEY, x, z) < 16 && noise(x, z, 4, 3) > 0.5)
|
|
204
|
+
grow(map, STYLE.tallGrass, (x, z) => distanceToLine(VALLEY, x, z) < 7 && noise(x, z, 5, 4) > 0.4)
|
|
205
|
+
grow(map, STYLE.reeds, (x, z) => distanceToLine(VALLEY, x, z) < 3)
|
|
206
|
+
mow(map, stream)
|
|
207
|
+
return map
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** The valley's trees: up its sides, pines high */
|
|
211
|
+
export const valleyTrees = (map: GameMap): At[] =>
|
|
212
|
+
scatter(map, (x, z) => distanceToLine(VALLEY, x, z) > 4 && noise(x, z, 6, 30) > 0.35, 1.8, 15, 1200)
|
|
213
|
+
|
|
214
|
+
/** A point on the valley's floor, `share` of the way up it */
|
|
215
|
+
export const valleyAt = (share: number): At => {
|
|
216
|
+
const i = Math.min(VALLEY.length - 2, Math.floor(share * (VALLEY.length - 1)))
|
|
217
|
+
const t = share * (VALLEY.length - 1) - i
|
|
218
|
+
return { x: VALLEY[i].x + (VALLEY[i + 1].x - VALLEY[i].x) * t, z: VALLEY[i].z + (VALLEY[i + 1].z - VALLEY[i].z) * t }
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ---- a village, for the weather and the time of day
|
|
222
|
+
|
|
223
|
+
/** The village square's middle */
|
|
224
|
+
export const SQUARE: At = { x: 32, z: 32 }
|
|
225
|
+
|
|
226
|
+
/** Where the village's lamps stand: torches round the square, each a light of the map too (`MapEnvironment.lights`) */
|
|
227
|
+
export const LAMPS: At[] = [
|
|
228
|
+
{ x: 27, z: 27 },
|
|
229
|
+
{ x: 37, z: 27 },
|
|
230
|
+
{ x: 27, z: 37 },
|
|
231
|
+
{ x: 37, z: 37 },
|
|
232
|
+
{ x: 32, z: 22 },
|
|
233
|
+
{ x: 32, z: 44 },
|
|
234
|
+
{ x: 20, z: 32 },
|
|
235
|
+
{ x: 44, z: 32 }
|
|
236
|
+
]
|
|
237
|
+
|
|
238
|
+
/** A village of 64 cells a side: houses round a square with a well and a fire, roads out, fields and woods about */
|
|
239
|
+
export function villageMap(): GameMap {
|
|
240
|
+
const map = field('Village', 64)
|
|
241
|
+
sculpt(map, rolling(0.5, 14))
|
|
242
|
+
const roads = [
|
|
243
|
+
band([{ x: 32, z: 0 }, { x: 31, z: 20 }, SQUARE, { x: 33, z: 46 }, { x: 32, z: 64 }], 2.4, 0.3, 3),
|
|
244
|
+
band([{ x: 0, z: 31 }, { x: 18, z: 33 }, SQUARE, { x: 46, z: 31 }, { x: 64, z: 34 }], 2.4, 0.3, 4)
|
|
245
|
+
]
|
|
246
|
+
const square = blob(SQUARE, 6.5, 0.6, 2)
|
|
247
|
+
grow(map, STYLE.meadow, (x, z) => noise(x, z, 9, 2) > 0.25)
|
|
248
|
+
grow(map, STYLE.wheat, (x, z) => x > 42 && x < 56 && z > 40 && z < 54)
|
|
249
|
+
grow(map, STYLE.wheat, (x, z) => x > 8 && x < 20 && z > 8 && z < 19)
|
|
250
|
+
grow(map, STYLE.flowers, (x, z) => noise(x, z, 4, 8) > 0.74)
|
|
251
|
+
paint(map, 'road', (x, z) => square(x, z) || roads.some((road) => road(x, z)))
|
|
252
|
+
mow(map, (x, z) => square(x, z) || roads.some((road) => road(x, z)))
|
|
253
|
+
const houses: [string, At, number][] = [
|
|
254
|
+
['village/fantasy_house.glb', { x: 24, z: 22 }, 0.6],
|
|
255
|
+
['village/fantasy_house_2.glb', { x: 41, z: 22 }, -0.7],
|
|
256
|
+
['village/fantasy_inn.glb', { x: 42, z: 41 }, -2.4],
|
|
257
|
+
['village/fantasy_house_3.glb', { x: 22, z: 41 }, 2.3],
|
|
258
|
+
['village/fantasy_house.glb', { x: 15, z: 27 }, 1.5],
|
|
259
|
+
['village/mill.glb', { x: 50, z: 17 }, -1],
|
|
260
|
+
['village/fantasy_stable.glb', { x: 15, z: 44 }, 2]
|
|
261
|
+
]
|
|
262
|
+
for (const [model, at, yaw] of houses) {
|
|
263
|
+
mow(map, blob(at, 3.2, 0.5))
|
|
264
|
+
place(map, model, at, { yaw, blocks: true })
|
|
265
|
+
}
|
|
266
|
+
place(map, 'village/well.glb', { x: 34.5, z: 30 }, { scale: 1.1 })
|
|
267
|
+
place(map, 'village/bonfire.glb', { x: 30, z: 34 }, { scale: 1.6, name: 'fire' })
|
|
268
|
+
place(map, 'village/market_stand.glb', { x: 28, z: 29 }, { yaw: 0.8 })
|
|
269
|
+
place(map, 'village/cart.glb', { x: 36, z: 36 }, { yaw: 2.4 })
|
|
270
|
+
place(map, 'village/barrel.glb', { x: 38.6, z: 25.8 })
|
|
271
|
+
place(map, 'village/hay.glb', { x: 46, z: 38 }, { yaw: 1 })
|
|
272
|
+
for (const at of LAMPS) place(map, 'dungeon-kit/torch.glb', at, { scale: 1.2 })
|
|
273
|
+
// a light at each torch's flame and at the fire, on always (a game without a day has no night to come on at); how
|
|
274
|
+
// bright all of them are is the map's lamps (`MapEnvironment.lamps`), which the time of day turns up at dusk
|
|
275
|
+
map.environment = {
|
|
276
|
+
...map.environment,
|
|
277
|
+
lights: [
|
|
278
|
+
...LAMPS.map((at, i) => ({
|
|
279
|
+
id: i + 1,
|
|
280
|
+
name: `torch ${i + 1}`,
|
|
281
|
+
...at,
|
|
282
|
+
height: 1.7,
|
|
283
|
+
color: [1, 0.68, 0.38] as Rgb,
|
|
284
|
+
intensity: 1.5,
|
|
285
|
+
range: 8,
|
|
286
|
+
flicker: 0.12,
|
|
287
|
+
halo: 0.3,
|
|
288
|
+
when: 'always' as const
|
|
289
|
+
})),
|
|
290
|
+
{
|
|
291
|
+
id: 20,
|
|
292
|
+
name: 'fire',
|
|
293
|
+
x: 30,
|
|
294
|
+
z: 34,
|
|
295
|
+
height: 0.9,
|
|
296
|
+
color: [1, 0.55, 0.25],
|
|
297
|
+
intensity: 2.2,
|
|
298
|
+
range: 11,
|
|
299
|
+
flicker: { amount: 0.3, speed: 1.4 },
|
|
300
|
+
when: 'always'
|
|
301
|
+
}
|
|
302
|
+
],
|
|
303
|
+
fx: [
|
|
304
|
+
{ id: 1, name: 'fire', fx: 'campfire', x: 30, z: 34, scale: 1.3 },
|
|
305
|
+
...LAMPS.map((at, i) => ({ id: i + 2, name: `torch ${i + 1}`, fx: 'torch', ...at, height: 1.55, scale: 0.8 }))
|
|
306
|
+
]
|
|
307
|
+
}
|
|
308
|
+
return map
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/** The village's trees: woods round its edge, a few in it */
|
|
312
|
+
export const villageTrees = (map: GameMap): At[] =>
|
|
313
|
+
scatter(
|
|
314
|
+
map,
|
|
315
|
+
(x, z) =>
|
|
316
|
+
(exactMath.hypot(x - SQUARE.x, z - SQUARE.z) > 26 || noise(x, z, 5, 3) > 0.82) &&
|
|
317
|
+
exactMath.hypot(x - SQUARE.x, z - SQUARE.z) > 9 &&
|
|
318
|
+
noise(x, z, 6, 40) > 0.3,
|
|
319
|
+
1.9,
|
|
320
|
+
16
|
|
321
|
+
).filter((at) => !onRoadOrHouse(at))
|
|
322
|
+
|
|
323
|
+
/** Whether a place is a road, the square or a house's ground: trees keep off */
|
|
324
|
+
function onRoadOrHouse({ x, z }: At): boolean {
|
|
325
|
+
return (
|
|
326
|
+
Math.abs(x - 32) < 3 ||
|
|
327
|
+
Math.abs(z - 32) < 3 ||
|
|
328
|
+
[
|
|
329
|
+
{ x: 24, z: 22 },
|
|
330
|
+
{ x: 41, z: 22 },
|
|
331
|
+
{ x: 42, z: 41 },
|
|
332
|
+
{ x: 22, z: 41 },
|
|
333
|
+
{ x: 15, z: 27 },
|
|
334
|
+
{ x: 50, z: 17 },
|
|
335
|
+
{ x: 15, z: 44 }
|
|
336
|
+
].some((house) => exactMath.hypot(x - house.x, z - house.z) < 5)
|
|
337
|
+
)
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// ---- a dry field by a wood, to burn
|
|
341
|
+
|
|
342
|
+
/** Where the fire is lit: the dry field's west end */
|
|
343
|
+
export const FIRE_START: At = { x: 14, z: 30 }
|
|
344
|
+
|
|
345
|
+
/** A field of 64 cells a side: dry grass in the west, meadow in the middle, a wood in the east, a road across */
|
|
346
|
+
export function fireMap(): GameMap {
|
|
347
|
+
const map = field('Dry field', 64)
|
|
348
|
+
sculpt(map, rolling(0.5, 16))
|
|
349
|
+
paint(map, 'dirt', (x, z) => noise(x, z, 6, 3) > 0.6)
|
|
350
|
+
grow(map, STYLE.dryGrass, (x, z) => x < 30 && noise(x, z, 8, 4) > 0.2)
|
|
351
|
+
grow(map, STYLE.meadow, (x, z) => x >= 26 && noise(x, z, 8, 4) > 0.25)
|
|
352
|
+
grow(map, STYLE.tallGrass, (x, z) => x > 22 && x < 40 && noise(x, z, 6, 5) > 0.6)
|
|
353
|
+
grow(map, STYLE.wheat, (x, z) => x > 28 && x < 38 && z > 6 && z < 20)
|
|
354
|
+
const road = band(
|
|
355
|
+
[
|
|
356
|
+
{ x: 0, z: 52 },
|
|
357
|
+
{ x: 30, z: 50 },
|
|
358
|
+
{ x: 64, z: 54 }
|
|
359
|
+
],
|
|
360
|
+
2.2
|
|
361
|
+
)
|
|
362
|
+
paint(map, 'road', road)
|
|
363
|
+
mow(map, road)
|
|
364
|
+
place(map, 'village/fantasy_house.glb', { x: 22, z: 56 }, { yaw: 3, blocks: true })
|
|
365
|
+
return map
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/** The fire's wood: east of the middle, and a few trees out in the field */
|
|
369
|
+
export const fireTrees = (map: GameMap): At[] =>
|
|
370
|
+
scatter(map, (x, z) => z < 48 && ((x > 38 && noise(x, z, 6, 7) > 0.25) || (x > 10 && noise(x, z, 4, 8) > 0.86)), 1.7, 17)
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skies for the nature examples: the look of the world at any hour of the day, and named looks to cross-fade between.
|
|
3
|
+
* Looks of the map (`MapEnvironment`) as data: given to `client.setEnvironment` they are one screen's, to
|
|
4
|
+
* `world.setEnvironment` every player's. The engine alone, so a map or the rules may take them too
|
|
5
|
+
*/
|
|
6
|
+
import { exactMath } from '@v12-engine/engine'
|
|
7
|
+
import type { MapEnvironment } from '@v12-engine/engine'
|
|
8
|
+
|
|
9
|
+
type Rgb = [number, number, number]
|
|
10
|
+
|
|
11
|
+
// ---- the time of day
|
|
12
|
+
|
|
13
|
+
/** The world at an hour: what the sun, the sky, the light, the mist and the lamps are */
|
|
14
|
+
interface HourLook {
|
|
15
|
+
hour: number
|
|
16
|
+
sky: Rgb
|
|
17
|
+
sun: number
|
|
18
|
+
sunColor: Rgb
|
|
19
|
+
ambient: number
|
|
20
|
+
ambientColor: Rgb
|
|
21
|
+
ground: Rgb
|
|
22
|
+
clouds: Rgb
|
|
23
|
+
fog: Rgb
|
|
24
|
+
mist: number
|
|
25
|
+
lamps: number
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** The day, hour by hour: night, dawn, morning, noon, afternoon, golden hour, dusk, night. Between two, mixed */
|
|
29
|
+
const DAY: HourLook[] = [
|
|
30
|
+
{
|
|
31
|
+
hour: 0,
|
|
32
|
+
sky: [0.03, 0.05, 0.12],
|
|
33
|
+
sun: 0.32,
|
|
34
|
+
sunColor: [0.55, 0.65, 1],
|
|
35
|
+
ambient: 0.22,
|
|
36
|
+
ambientColor: [0.35, 0.42, 0.75],
|
|
37
|
+
ground: [0.08, 0.08, 0.14],
|
|
38
|
+
clouds: [0.2, 0.22, 0.32],
|
|
39
|
+
fog: [0.06, 0.08, 0.16],
|
|
40
|
+
mist: 0.3,
|
|
41
|
+
lamps: 1
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
hour: 4.5,
|
|
45
|
+
sky: [0.06, 0.08, 0.18],
|
|
46
|
+
sun: 0.3,
|
|
47
|
+
sunColor: [0.55, 0.65, 1],
|
|
48
|
+
ambient: 0.24,
|
|
49
|
+
ambientColor: [0.38, 0.44, 0.75],
|
|
50
|
+
ground: [0.08, 0.08, 0.14],
|
|
51
|
+
clouds: [0.24, 0.26, 0.36],
|
|
52
|
+
fog: [0.08, 0.1, 0.2],
|
|
53
|
+
mist: 0.35,
|
|
54
|
+
lamps: 1
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
hour: 6,
|
|
58
|
+
sky: [0.75, 0.55, 0.55],
|
|
59
|
+
sun: 0.75,
|
|
60
|
+
sunColor: [1, 0.55, 0.35],
|
|
61
|
+
ambient: 0.4,
|
|
62
|
+
ambientColor: [0.75, 0.65, 0.85],
|
|
63
|
+
ground: [0.2, 0.17, 0.18],
|
|
64
|
+
clouds: [1, 0.7, 0.6],
|
|
65
|
+
fog: [0.8, 0.62, 0.6],
|
|
66
|
+
mist: 0.45,
|
|
67
|
+
lamps: 0.6
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
hour: 8,
|
|
71
|
+
sky: [0.6, 0.72, 0.88],
|
|
72
|
+
sun: 1.15,
|
|
73
|
+
sunColor: [1, 0.85, 0.68],
|
|
74
|
+
ambient: 0.5,
|
|
75
|
+
ambientColor: [0.85, 0.88, 1],
|
|
76
|
+
ground: [0.3, 0.28, 0.25],
|
|
77
|
+
clouds: [1, 0.95, 0.9],
|
|
78
|
+
fog: [0.75, 0.78, 0.82],
|
|
79
|
+
mist: 0.15,
|
|
80
|
+
lamps: 0
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
hour: 12,
|
|
84
|
+
sky: [0.46, 0.66, 0.92],
|
|
85
|
+
sun: 1.45,
|
|
86
|
+
sunColor: [1, 0.97, 0.9],
|
|
87
|
+
ambient: 0.6,
|
|
88
|
+
ambientColor: [0.92, 0.96, 1],
|
|
89
|
+
ground: [0.35, 0.33, 0.3],
|
|
90
|
+
clouds: [1, 1, 1],
|
|
91
|
+
fog: [0.72, 0.8, 0.9],
|
|
92
|
+
mist: 0,
|
|
93
|
+
lamps: 0
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
hour: 16,
|
|
97
|
+
sky: [0.5, 0.66, 0.88],
|
|
98
|
+
sun: 1.35,
|
|
99
|
+
sunColor: [1, 0.92, 0.78],
|
|
100
|
+
ambient: 0.55,
|
|
101
|
+
ambientColor: [0.9, 0.92, 1],
|
|
102
|
+
ground: [0.33, 0.3, 0.27],
|
|
103
|
+
clouds: [1, 0.97, 0.92],
|
|
104
|
+
fog: [0.75, 0.78, 0.85],
|
|
105
|
+
mist: 0,
|
|
106
|
+
lamps: 0
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
hour: 18,
|
|
110
|
+
sky: [0.85, 0.58, 0.42],
|
|
111
|
+
sun: 1.05,
|
|
112
|
+
sunColor: [1, 0.62, 0.32],
|
|
113
|
+
ambient: 0.42,
|
|
114
|
+
ambientColor: [0.85, 0.65, 0.65],
|
|
115
|
+
ground: [0.25, 0.18, 0.15],
|
|
116
|
+
clouds: [1, 0.68, 0.48],
|
|
117
|
+
fog: [0.85, 0.6, 0.48],
|
|
118
|
+
mist: 0.15,
|
|
119
|
+
lamps: 0.4
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
hour: 19.5,
|
|
123
|
+
sky: [0.32, 0.25, 0.42],
|
|
124
|
+
sun: 0.5,
|
|
125
|
+
sunColor: [0.85, 0.45, 0.45],
|
|
126
|
+
ambient: 0.3,
|
|
127
|
+
ambientColor: [0.5, 0.42, 0.7],
|
|
128
|
+
ground: [0.12, 0.1, 0.14],
|
|
129
|
+
clouds: [0.6, 0.42, 0.52],
|
|
130
|
+
fog: [0.3, 0.24, 0.36],
|
|
131
|
+
mist: 0.3,
|
|
132
|
+
lamps: 0.9
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
hour: 21,
|
|
136
|
+
sky: [0.05, 0.07, 0.16],
|
|
137
|
+
sun: 0.32,
|
|
138
|
+
sunColor: [0.55, 0.65, 1],
|
|
139
|
+
ambient: 0.22,
|
|
140
|
+
ambientColor: [0.35, 0.42, 0.75],
|
|
141
|
+
ground: [0.08, 0.08, 0.14],
|
|
142
|
+
clouds: [0.2, 0.22, 0.32],
|
|
143
|
+
fog: [0.06, 0.08, 0.16],
|
|
144
|
+
mist: 0.3,
|
|
145
|
+
lamps: 1
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
hour: 24,
|
|
149
|
+
sky: [0.03, 0.05, 0.12],
|
|
150
|
+
sun: 0.32,
|
|
151
|
+
sunColor: [0.55, 0.65, 1],
|
|
152
|
+
ambient: 0.22,
|
|
153
|
+
ambientColor: [0.35, 0.42, 0.75],
|
|
154
|
+
ground: [0.08, 0.08, 0.14],
|
|
155
|
+
clouds: [0.2, 0.22, 0.32],
|
|
156
|
+
fog: [0.06, 0.08, 0.16],
|
|
157
|
+
mist: 0.3,
|
|
158
|
+
lamps: 1
|
|
159
|
+
}
|
|
160
|
+
]
|
|
161
|
+
|
|
162
|
+
const mix = (a: number, b: number, t: number) => a + (b - a) * t
|
|
163
|
+
const mixRgb = (a: Rgb, b: Rgb, t: number): Rgb => [mix(a[0], b[0], t), mix(a[1], b[1], t), mix(a[2], b[2], t)]
|
|
164
|
+
|
|
165
|
+
/** Where the sun (or by night the moon) stands at an hour: degrees round from north, and up from the horizon */
|
|
166
|
+
function sunAt(hour: number): { around: number; up: number } {
|
|
167
|
+
const day = (hour - 6) / 12
|
|
168
|
+
if (day >= 0 && day <= 1) return { around: 90 + day * 180, up: Math.max(4, exactMath.sin(day * Math.PI) * 68) }
|
|
169
|
+
// the moon: across the sky the other way, never as high
|
|
170
|
+
const night = (((hour - 18 + 24) % 24) / 12) % 1
|
|
171
|
+
return { around: 90 + night * 180, up: Math.max(12, exactMath.sin(night * Math.PI) * 45) }
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** The look of the world at an hour, 0 to 24: the sun's place and colour, the sky, the clouds, the mist and the lamps */
|
|
175
|
+
export function lookAtHour(hour: number): Partial<MapEnvironment> {
|
|
176
|
+
const h = ((hour % 24) + 24) % 24
|
|
177
|
+
const next = DAY.findIndex((each) => each.hour > h)
|
|
178
|
+
const a = DAY[Math.max(0, next - 1)]
|
|
179
|
+
const b = DAY[next < 0 ? DAY.length - 1 : next]
|
|
180
|
+
const t = b.hour > a.hour ? (h - a.hour) / (b.hour - a.hour) : 0
|
|
181
|
+
const sun = sunAt(h)
|
|
182
|
+
return {
|
|
183
|
+
sky: mixRgb(a.sky, b.sky, t),
|
|
184
|
+
clouds: { cover: 0.35, color: mixRgb(a.clouds, b.clouds, t) },
|
|
185
|
+
light: {
|
|
186
|
+
sunAround: sun.around,
|
|
187
|
+
sunUp: sun.up,
|
|
188
|
+
sun: mix(a.sun, b.sun, t),
|
|
189
|
+
sunColor: mixRgb(a.sunColor, b.sunColor, t),
|
|
190
|
+
ambient: mix(a.ambient, b.ambient, t),
|
|
191
|
+
ambientColor: mixRgb(a.ambientColor, b.ambientColor, t),
|
|
192
|
+
ground: mixRgb(a.ground, b.ground, t),
|
|
193
|
+
// the glow at dawn and dusk is the table's own
|
|
194
|
+
glow: false
|
|
195
|
+
},
|
|
196
|
+
fog: { start: 50, end: 170, color: mixRgb(a.fog, b.fog, t) },
|
|
197
|
+
mist: { ground: { base: 0, top: 1.8, density: mix(a.mist, b.mist, t), color: mixRgb(a.fog, b.fog, t) } },
|
|
198
|
+
lamps: { brightness: mix(a.lamps, b.lamps, t) }
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** How much the lamps are lit at an hour, 0 to 1 */
|
|
203
|
+
export const lampsAtHour = (hour: number): number => (lookAtHour(hour).lamps?.brightness as number) ?? 0
|
|
204
|
+
|
|
205
|
+
/** An hour as a clock shows it */
|
|
206
|
+
export const clock = (hour: number): string => {
|
|
207
|
+
const h = ((hour % 24) + 24) % 24
|
|
208
|
+
return `${String(Math.floor(h)).padStart(2, '0')}:${String(Math.floor((h % 1) * 60)).padStart(2, '0')}`
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// ---- named looks, to cross-fade between
|
|
212
|
+
|
|
213
|
+
/** Looks of the world by name: what the looks example picks from. Each says all of what it changes, so any follows any */
|
|
214
|
+
export const LOOKS: Record<string, Partial<MapEnvironment>> = {
|
|
215
|
+
'Summer noon': {
|
|
216
|
+
...lookAtHour(12),
|
|
217
|
+
clouds: { cover: 0.3 },
|
|
218
|
+
cloudLayer: { height: 22, cover: 0.3, opacity: 0.5, shadows: 0.4 },
|
|
219
|
+
wind: { around: 100, strength: 0.3, gusts: 0.3 },
|
|
220
|
+
weather: { kind: 'rain', amount: 0 },
|
|
221
|
+
water: { shallow: [0.3, 0.62, 0.6], deep: [0.05, 0.2, 0.3], waves: { strength: 0.6 } }
|
|
222
|
+
},
|
|
223
|
+
'Golden hour': {
|
|
224
|
+
...lookAtHour(17.6),
|
|
225
|
+
light: { ...lookAtHour(17.6).light, sun: 1.35, ambient: 0.55 },
|
|
226
|
+
clouds: { cover: 0.45, color: [1, 0.72, 0.5] },
|
|
227
|
+
cloudLayer: { height: 24, cover: 0.35, opacity: 0.55, shadows: 0.35, color: [1, 0.8, 0.65] },
|
|
228
|
+
wind: { around: 80, strength: 0.2, gusts: 0.2 },
|
|
229
|
+
weather: { kind: 'rain', amount: 0 },
|
|
230
|
+
water: { shallow: [0.5, 0.6, 0.6], deep: [0.12, 0.2, 0.3], waves: { strength: 0.5 } }
|
|
231
|
+
},
|
|
232
|
+
'Blue night': {
|
|
233
|
+
...lookAtHour(0.5),
|
|
234
|
+
clouds: { cover: 0.2, color: [0.25, 0.28, 0.4] },
|
|
235
|
+
cloudLayer: { height: 22, cover: 0.2, opacity: 0.3, shadows: 0.2 },
|
|
236
|
+
wind: { around: 80, strength: 0.15, gusts: 0.2 },
|
|
237
|
+
weather: { kind: 'rain', amount: 0 },
|
|
238
|
+
water: { shallow: [0.12, 0.2, 0.32], deep: [0.02, 0.04, 0.1], waves: { strength: 0.4 } }
|
|
239
|
+
},
|
|
240
|
+
'Grey storm': {
|
|
241
|
+
sky: [0.24, 0.27, 0.32],
|
|
242
|
+
clouds: { cover: 0.95, speed: 2.5, color: [0.4, 0.42, 0.46] },
|
|
243
|
+
cloudLayer: { height: 14, cover: 0.85, opacity: 0.75, shadows: 0.6, scale: 18 },
|
|
244
|
+
light: {
|
|
245
|
+
sunUp: 35,
|
|
246
|
+
sunAround: 200,
|
|
247
|
+
sun: 0.45,
|
|
248
|
+
sunColor: [0.75, 0.82, 1],
|
|
249
|
+
ambient: 0.4,
|
|
250
|
+
ambientColor: [0.6, 0.66, 0.8],
|
|
251
|
+
ground: [0.15, 0.15, 0.17],
|
|
252
|
+
glow: false
|
|
253
|
+
},
|
|
254
|
+
wind: { around: 120, strength: 0.95, gusts: 0.9 },
|
|
255
|
+
weather: { kind: 'rain', amount: 1, splashes: 1, size: 1.2, speed: 1.3 },
|
|
256
|
+
fog: { start: 25, end: 95, color: [0.3, 0.33, 0.38] },
|
|
257
|
+
mist: { ground: { base: 0, top: 2.5, density: 0.4, color: [0.4, 0.43, 0.5] } },
|
|
258
|
+
lamps: { brightness: 0.8 },
|
|
259
|
+
water: { shallow: [0.25, 0.32, 0.34], deep: [0.06, 0.09, 0.12], waves: { strength: 1, length: 2.2, speed: 2 } }
|
|
260
|
+
},
|
|
261
|
+
'Winter morning': {
|
|
262
|
+
sky: [0.78, 0.82, 0.9],
|
|
263
|
+
clouds: { cover: 0.7, color: [0.95, 0.95, 0.98] },
|
|
264
|
+
cloudLayer: { height: 20, cover: 0.5, opacity: 0.45, shadows: 0.3 },
|
|
265
|
+
light: {
|
|
266
|
+
sunUp: 18,
|
|
267
|
+
sunAround: 120,
|
|
268
|
+
sun: 1,
|
|
269
|
+
sunColor: [1, 0.9, 0.8],
|
|
270
|
+
ambient: 0.75,
|
|
271
|
+
ambientColor: [0.85, 0.9, 1],
|
|
272
|
+
ground: [0.5, 0.52, 0.56],
|
|
273
|
+
glow: false
|
|
274
|
+
},
|
|
275
|
+
wind: { around: 60, strength: 0.25, gusts: 0.3 },
|
|
276
|
+
weather: { kind: 'snow', amount: 0.55, settle: 1 },
|
|
277
|
+
fog: { start: 40, end: 140, color: [0.86, 0.88, 0.92] },
|
|
278
|
+
mist: { ground: { base: 0, top: 2, density: 0.3, color: [0.92, 0.93, 0.96] } },
|
|
279
|
+
lamps: { brightness: 0.3 },
|
|
280
|
+
water: { shallow: [0.55, 0.68, 0.72], deep: [0.15, 0.25, 0.32], waves: { strength: 0.25 } }
|
|
281
|
+
},
|
|
282
|
+
'Autumn haze': {
|
|
283
|
+
sky: [0.85, 0.7, 0.52],
|
|
284
|
+
clouds: { cover: 0.5, color: [1, 0.85, 0.7] },
|
|
285
|
+
cloudLayer: { height: 24, cover: 0.3, opacity: 0.4, shadows: 0.25, color: [1, 0.9, 0.75] },
|
|
286
|
+
light: {
|
|
287
|
+
sunUp: 28,
|
|
288
|
+
sunAround: 230,
|
|
289
|
+
sun: 1.15,
|
|
290
|
+
sunColor: [1, 0.75, 0.48],
|
|
291
|
+
ambient: 0.5,
|
|
292
|
+
ambientColor: [0.95, 0.8, 0.65],
|
|
293
|
+
ground: [0.3, 0.22, 0.15],
|
|
294
|
+
glow: false
|
|
295
|
+
},
|
|
296
|
+
wind: { around: 220, strength: 0.35, gusts: 0.5 },
|
|
297
|
+
weather: { kind: 'rain', amount: 0 },
|
|
298
|
+
fog: { start: 25, end: 120, color: [0.85, 0.66, 0.46] },
|
|
299
|
+
mist: { ground: { base: 0, top: 3, density: 0.35, color: [0.9, 0.72, 0.52] } },
|
|
300
|
+
lamps: { brightness: 0.2 },
|
|
301
|
+
water: { shallow: [0.45, 0.48, 0.35], deep: [0.12, 0.15, 0.12], waves: { strength: 0.4 } }
|
|
302
|
+
},
|
|
303
|
+
'Eerie green': {
|
|
304
|
+
sky: [0.2, 0.3, 0.22],
|
|
305
|
+
clouds: { cover: 0.8, color: [0.45, 0.6, 0.45] },
|
|
306
|
+
cloudLayer: { height: 16, cover: 0.6, opacity: 0.6, shadows: 0.5, color: [0.6, 0.8, 0.6] },
|
|
307
|
+
light: {
|
|
308
|
+
sunUp: 30,
|
|
309
|
+
sunAround: 300,
|
|
310
|
+
sun: 0.7,
|
|
311
|
+
sunColor: [0.7, 1, 0.7],
|
|
312
|
+
ambient: 0.4,
|
|
313
|
+
ambientColor: [0.5, 0.8, 0.55],
|
|
314
|
+
ground: [0.1, 0.16, 0.1],
|
|
315
|
+
glow: false
|
|
316
|
+
},
|
|
317
|
+
wind: { around: 0, strength: 0.1, gusts: 0.6 },
|
|
318
|
+
weather: { kind: 'rain', amount: 0 },
|
|
319
|
+
fog: { start: 15, end: 90, color: [0.25, 0.38, 0.26] },
|
|
320
|
+
mist: { ground: { base: 0, top: 3.5, density: 0.6, color: [0.4, 0.6, 0.42] } },
|
|
321
|
+
lamps: { brightness: 1 },
|
|
322
|
+
water: { shallow: [0.22, 0.4, 0.2], deep: [0.04, 0.1, 0.05], waves: { strength: 0.2 } }
|
|
323
|
+
}
|
|
324
|
+
}
|