incanto 0.20.0 → 0.22.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/dist/2d.js +3 -3
- package/dist/3d.d.ts +68 -0
- package/dist/3d.js +4 -3
- package/dist/{create-game-Ct86zczq.js → create-game-B-M1zune.js} +3 -3
- package/dist/{create-game-pNf3sI-Q.js → create-game-C3uiw80V.js} +6 -3
- package/dist/{duplicate-BINwP0WG.js → duplicate-BgtFrFo4.js} +15 -1
- package/dist/gameplay-Dib5mNFD.js +5425 -0
- package/dist/gameplay.js +1 -1
- package/dist/index.js +3 -3
- package/dist/{particle-sim-CyUU7HVU.js → particle-sim-Bw7hB93B.js} +1 -15
- package/dist/{physics-2d-BiIdl51r.js → physics-2d-DiVFFlH3.js} +1 -1
- package/dist/{physics-3d-DxFDfUey.js → physics-3d-DLPPRNu4.js} +2 -1
- package/dist/react.js +1 -1
- package/dist/{register-BWFgsGra.js → register-CHgVdSbp.js} +150 -3143
- package/dist/{register-Djwckzgx.js → register-CvpSUU3O.js} +2 -1
- package/dist/test.js +7 -7
- package/editor/assets/{agent8-BZX7dF4f.js → agent8-4yMWrtSC.js} +1 -1
- package/editor/assets/{index-CXdpxO_B.js → index-DAzNRDSQ.js} +2988 -2822
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +8 -0
- package/skills/incanto-environment.md +56 -0
- package/skills/incanto-gameplay-behaviors.md +36 -1
- package/skills/incanto-node-reference.md +17 -0
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/village-quest-3d/package.json +1 -1
- package/dist/gameplay-sSqrUcnz.js +0 -1978
package/editor/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Incanto Scene Editor</title>
|
|
7
7
|
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><rect width='16' height='16' rx='3' fill='%236ee7dc'/><text x='8' y='12' text-anchor='middle' font-size='11' font-family='monospace' fill='%230e1018'>i</text></svg>" />
|
|
8
|
-
<script type="module" crossorigin src="./assets/index-
|
|
8
|
+
<script type="module" crossorigin src="./assets/index-DAzNRDSQ.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="./assets/GameServer-C56iOUgF.js">
|
|
10
10
|
<link rel="stylesheet" crossorigin href="./assets/index-D8QvwvOm.css">
|
|
11
11
|
</head>
|
package/package.json
CHANGED
|
@@ -4735,6 +4735,10 @@
|
|
|
4735
4735
|
"flowForce": {
|
|
4736
4736
|
"type": "number",
|
|
4737
4737
|
"default": 1
|
|
4738
|
+
},
|
|
4739
|
+
"spray": {
|
|
4740
|
+
"type": "number",
|
|
4741
|
+
"default": 1
|
|
4738
4742
|
}
|
|
4739
4743
|
},
|
|
4740
4744
|
"additionalProperties": false
|
|
@@ -6579,6 +6583,10 @@
|
|
|
6579
6583
|
"type": "boolean",
|
|
6580
6584
|
"default": false
|
|
6581
6585
|
},
|
|
6586
|
+
"swellSteepness": {
|
|
6587
|
+
"type": "number",
|
|
6588
|
+
"default": 0.35
|
|
6589
|
+
},
|
|
6582
6590
|
"foam": {
|
|
6583
6591
|
"type": "boolean",
|
|
6584
6592
|
"default": true
|
|
@@ -699,6 +699,7 @@ hue reads grey.
|
|
|
699
699
|
| `reflection` | `true` | live CubeCamera reflections (fancy only; needs a renderer) |
|
|
700
700
|
| `reflectionInterval` | `1000` | ms between CubeCamera reflection re-renders |
|
|
701
701
|
| `mirror` | `false` | TRUE planar reflection (see below) — the only way the dock, the boat and the player appear IN the water. One extra scene render per frame |
|
|
702
|
+
| `swellSteepness` | `0.35` | GERSTNER pinch on the swell: 0 = height-only trains, 1 = maximum trochoid (crests narrow to a peak, troughs broaden). It also decides where whitecaps break — the surface's Jacobian collapses on a folding crest, and that is where foam belongs |
|
|
702
703
|
| `foam` | `true` | noise-broken shoreline foam band + crest foam near shores |
|
|
703
704
|
| `interaction` | `true` | character interaction: bodies (CharacterBody3D/RigidBody3D) inside the XZ footprint whose FEET dip below the surface count as in-water — so a WADING character (origin above water, feet below, sized from its collider) splashes, not only a fully-submerged one. Entry/exit emit `entered`/`exited` + a splash ripple; striding through water trails a WAKE (a ripple every ~0.45 m); floating bodies bob gently. Ripples drive both shaders' `uRipples[8]` (fancy) and CPU-displace the mesh (`simple`) |
|
|
704
705
|
| `splash` | `true` | built-in splash WHITEWATER (needs `interaction`): the shaders paint expanding **surface foam** where bodies interact — a **"풍덩"** froth bloom when a body plunges in (bigger the faster it falls) and a **foam trail ("물살")** behind a body wading/running through. Real frothy whitewater on the surface, not flying droplets; works on both `fancy` and `simple` quality. `false` keeps the ripples/waves but paints no foam. No wiring needed; for an extra custom burst add your own `Particles3D` on the `entered` signal |
|
|
@@ -765,6 +766,28 @@ plane and samples it per fragment, so those things appear in the water:
|
|
|
765
766
|
- Geometry below the waterline is clipped out of the mirror pass, and the whole
|
|
766
767
|
pass is skipped while the camera is submerged.
|
|
767
768
|
|
|
769
|
+
### Under the surface
|
|
770
|
+
|
|
771
|
+
Swimming down is a different optical world, and the engine renders it as one:
|
|
772
|
+
|
|
773
|
+
- **Light shafts** hang in the water column toward the sun — `underwater.rays`
|
|
774
|
+
(`true` by default, a number sets the strength, `false` turns them off). The
|
|
775
|
+
composite marches each view ray and, at every step, walks UP the sun direction
|
|
776
|
+
to the surface: the pattern sampled there is what that beam carries down, so
|
|
777
|
+
shafts converge with depth and shimmer with the same surface that makes the
|
|
778
|
+
caustics. They need DEPTH to read — a knee-deep pool has no column to light.
|
|
779
|
+
- **Caustics** light what those beams land on (`underwater.caustics`).
|
|
780
|
+
- **Snell's window**: light can only leave into the air inside a ~48.6° cone,
|
|
781
|
+
so from below the surface is a bright disc of sky ringed by a mirror of the
|
|
782
|
+
water you are in. That image is what everyone recognises as "underwater", and
|
|
783
|
+
the surface shader draws it whenever the camera eye is submerged.
|
|
784
|
+
|
|
785
|
+
```json
|
|
786
|
+
{ "type": "Water3D", "props": { "preset": "ocean",
|
|
787
|
+
"underwater": { "visibility": 26, "rays": 0.8,
|
|
788
|
+
"caustics": { "intensity": 0.6 } } } }
|
|
789
|
+
```
|
|
790
|
+
|
|
768
791
|
### Character interaction — `entered(body)` / `exited(body)`
|
|
769
792
|
|
|
770
793
|
With `interaction: true` the water scans the tree each frame for
|
|
@@ -837,6 +860,7 @@ underneath decides everything else.
|
|
|
837
860
|
| `ripples` | `1` | surface-detail dial (ripple relief + glitter) |
|
|
838
861
|
| `terrain` | `''` | drape target path; empty = auto-find the first Terrain3D (a wrong path fails at load) |
|
|
839
862
|
| `flowForce` | `1` | how hard the current sweeps bodies downstream (0 = visual only) |
|
|
863
|
+
| `spray` | `1` | mist at the foot of every waterfall the course turns out to contain — the node finds the drops and hangs a Particles3D plume on each (0 = off) |
|
|
840
864
|
| `sunDirection` / `sunColor` / `sunIntensity` | sky / `#fff6e0` / `1` | glint (the environment sun wins while `sunDirection` is default) |
|
|
841
865
|
|
|
842
866
|
**What the node derives for you**, all from `path` + the ground:
|
|
@@ -868,6 +892,38 @@ const path = traceDownhillPath(terrain.heightAt, { x: peakX, z: peakZ, step: 7 }
|
|
|
868
892
|
"path": path, "widths": [2.4, 4.5, 7, 9], "depth": 1
|
|
869
893
|
```
|
|
870
894
|
|
|
895
|
+
### Waterfalls happen — you do not author them
|
|
896
|
+
|
|
897
|
+
Nothing in a scene says "waterfall". Where the ground gives way the surface
|
|
898
|
+
profile falls with it, and past ~20° of grade the shader stops treating the
|
|
899
|
+
sheet as flowing water: it aerates (white, diffuse, no sky reflection), its
|
|
900
|
+
pattern stretches into strands, the standing waves of a rapid switch off, and
|
|
901
|
+
the lip goes glassy-dark for the moment before it breaks. `spray` then hangs a
|
|
902
|
+
mist plume at the foot of each drop, sized by how far the water fell.
|
|
903
|
+
|
|
904
|
+
The cheapest way to put one in a scene is to take the ground away — a
|
|
905
|
+
`basins` pocket on the course, no wider than the creek's own reach:
|
|
906
|
+
|
|
907
|
+
```ts
|
|
908
|
+
const plungeAt = path[Math.round(path.length * 0.82)];
|
|
909
|
+
"basins": [{ "x": plungeAt[0], "z": plungeAt[1], "radius": 7, "depth": 4.5 }]
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
Keep it a POCKET: a wide shallow bowl reads as a crater with a puddle, and the
|
|
913
|
+
drop has to be short and sharp for the curtain to read at all. For your own
|
|
914
|
+
effects (sound, a rainbow, a cave behind the water), `river.fallsAt()` returns
|
|
915
|
+
every drop with its plunge point in WORLD coordinates and its height:
|
|
916
|
+
|
|
917
|
+
```ts
|
|
918
|
+
for (const fall of creek.fallsAt()) {
|
|
919
|
+
if (fall.drop > 4) playAt('$sfx/falls', fall.worldX, fall.worldY, fall.worldZ);
|
|
920
|
+
}
|
|
921
|
+
```
|
|
922
|
+
|
|
923
|
+
A step shallower than the water's own `depth` is deliberately NOT a fall — the
|
|
924
|
+
surface profile treats it as bed grain, which is what stops every riffle in a
|
|
925
|
+
creek from spawning a spray plume.
|
|
926
|
+
|
|
871
927
|
### Let the terrain choose the course — `traceDownhillPath`
|
|
872
928
|
|
|
873
929
|
```ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: incanto-gameplay-behaviors
|
|
3
|
-
description: The batteries-included game-logic library (incanto/gameplay) — ready-made Behaviors you wire from scene JSON with ZERO custom code. State & interaction: Health (hit points, i-frames, regen), Lifetime (self-destruct), ScoreKeeper (score/lives/win-lose hub), Pickup (collectibles), Collector (collect-N tally), DamageOnContact (projectiles/hazards), Interactable (press-to-use doors/levers/NPCs). Movement, AI, camera, spawning & juice: FollowCamera (camera tracks a target), Patrol (waypoint paths), Chase (homing enemy AI), Wander (seeded roaming), ZombieAI (wander-then-charge monster AI with proximity aggro), MoveTo (eased position tween), Oscillate (sine float/spin/pulse), Spawner (interval spawning), WaveSpawner (sequenced enemy waves), Projectile (straight-line motion). Use when a game needs health, score, pickups, damage, timers, interaction, enemy movement/AI, camera-follow, tweens,
|
|
3
|
+
description: The batteries-included game-logic library (incanto/gameplay) — ready-made Behaviors you wire from scene JSON with ZERO custom code. State & interaction: Health (hit points, i-frames, regen), Lifetime (self-destruct), ScoreKeeper (score/lives/win-lose hub), Pickup (collectibles), Collector (collect-N tally), DamageOnContact (projectiles/hazards), Interactable (press-to-use doors/levers/NPCs). Movement, AI, camera, spawning & juice: FollowCamera (camera tracks a target), Patrol (waypoint paths), Chase (homing enemy AI), Wander (seeded roaming), ZombieAI (wander-then-charge monster AI with proximity aggro), MoveTo (eased position tween), Oscillate (sine float/spin/pulse), Spawner (interval spawning), WaveSpawner (sequenced enemy waves), Projectile (straight-line motion), Buoyancy (float/bob/ride the swell on a Water3D). Use when a game needs health, score, pickups, damage, timers, interaction, enemy movement/AI, camera-follow, tweens, spawning, rafts/boats/floating objects — BEFORE hand-rolling them as custom behaviors.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Gameplay behaviors — the built-in logic library
|
|
@@ -460,6 +460,41 @@ pickups, spinning/pulsing coins. Drives one `axis` of `position`, `rotation`
|
|
|
460
460
|
"script": { "name": "Oscillate", "props": { "axis": "z", "amplitude": 180, "frequency": 0.5, "mode": "rotation" } } }
|
|
461
461
|
```
|
|
462
462
|
|
|
463
|
+
## Buoyancy
|
|
464
|
+
|
|
465
|
+
Float on water. Hangs on a `RigidBody3D` and asks the water how high it is at
|
|
466
|
+
each of the hull's sample points — the CPU twin of the surface the player is
|
|
467
|
+
actually looking at, waves included — then pushes up by how deep each point
|
|
468
|
+
sits, damped by how fast it is already rising. Archimedes plus drag, which is
|
|
469
|
+
all a raft, a buoy, a crate or a body needs to bob, settle and ride the swell.
|
|
470
|
+
|
|
471
|
+
| Prop | Default | Meaning |
|
|
472
|
+
|---|---|---|
|
|
473
|
+
| `water` | `""` | Water3D node path; empty = the first Water3D in the tree (a wrong path fails hard) |
|
|
474
|
+
| `draft` | `0.35` | how deep the hull sits at rest, in meters (its waterline below the body origin) |
|
|
475
|
+
| `stiffness` | `14` | float stiffness (1/s²) — higher snaps to the surface, lower wallows |
|
|
476
|
+
| `damping` | `3.5` | vertical damping (1/s) — how fast the bobbing settles |
|
|
477
|
+
| `drift` | `0.6` | how hard wave SLOPES carry the body along (0 = bob on the spot) |
|
|
478
|
+
| `drag` | `0.9` | horizontal drag while submerged (1/s) |
|
|
479
|
+
| `samples` | `4` | 1 = a buoy, 4 = a hull that reads the wave under it |
|
|
480
|
+
| `size` | `[1, 1]` | hull footprint [x, z] in meters — where those samples sit |
|
|
481
|
+
|
|
482
|
+
Signals: `submerged(node)` / `surfaced(node)` as it crosses the waterline —
|
|
483
|
+
wire them to a splash `Particles3D`, a sound, or a "you dropped the cargo" rule.
|
|
484
|
+
|
|
485
|
+
```json
|
|
486
|
+
{ "name": "Raft", "type": "RigidBody3D", "props": { "mass": 120 },
|
|
487
|
+
"script": { "name": "Buoyancy", "props": { "draft": 0.25, "size": [2.4, 1.4], "drift": 0.8 } } }
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
`drift` is the part players notice: a wave face is a slope, and a floating
|
|
491
|
+
thing slides down it, so a raft left alone wanders with the swell instead of
|
|
492
|
+
bobbing on the spot. The lift is capped at a few g — water pushes back, it
|
|
493
|
+
never launches a body that has been dragged deep.
|
|
494
|
+
|
|
495
|
+
For the water's own height anywhere (jetties, spawn heights, an AI deciding
|
|
496
|
+
where the shore is), `Water3D.heightAt(x, z)` answers the same surface.
|
|
497
|
+
|
|
463
498
|
## Spawner
|
|
464
499
|
|
|
465
500
|
Drip-feed clones of a TEMPLATE into the scene on a timer — enemy generators,
|
|
@@ -696,6 +696,7 @@ Signals: `triggerEnter(other)` · `triggerExit(other)`
|
|
|
696
696
|
| `sunIntensity` | `1` | number |
|
|
697
697
|
| `terrain` | `""` | string |
|
|
698
698
|
| `flowForce` | `1` | number |
|
|
699
|
+
| `spray` | `1` | number |
|
|
699
700
|
|
|
700
701
|
## `Sprite2D` — `incanto/2d`
|
|
701
702
|
|
|
@@ -973,6 +974,7 @@ Signals: `blocksChanged`
|
|
|
973
974
|
| `reflection` | `true` | boolean |
|
|
974
975
|
| `reflectionInterval` | `1000` | number |
|
|
975
976
|
| `mirror` | `false` | boolean |
|
|
977
|
+
| `swellSteepness` | `0.35` | number |
|
|
976
978
|
| `foam` | `true` | boolean |
|
|
977
979
|
| `interaction` | `true` | boolean |
|
|
978
980
|
| `splash` | `true` | boolean |
|
|
@@ -999,6 +1001,21 @@ Ready-made `Behavior`s auto-registered by `createGame2D`/`createGame3D` (opt out
|
|
|
999
1001
|
with `gameplay: false`). Attach via `"script": {"name": "...", "props": {...}}` and
|
|
1000
1002
|
wire their signals through scene `connections`. Full guide: `incanto-gameplay-behaviors.md`.
|
|
1001
1003
|
|
|
1004
|
+
### `Buoyancy`
|
|
1005
|
+
|
|
1006
|
+
| Prop | Default | Kind |
|
|
1007
|
+
|---|---|---|
|
|
1008
|
+
| `water` | `""` | string |
|
|
1009
|
+
| `draft` | `0.35` | number |
|
|
1010
|
+
| `stiffness` | `14` | number |
|
|
1011
|
+
| `damping` | `3.5` | number |
|
|
1012
|
+
| `drift` | `0.6` | number |
|
|
1013
|
+
| `drag` | `0.9` | number |
|
|
1014
|
+
| `samples` | `4` | number |
|
|
1015
|
+
| `size` | `[1,1]` | array |
|
|
1016
|
+
|
|
1017
|
+
Signals: `submerged` · `surfaced`
|
|
1018
|
+
|
|
1002
1019
|
### `CameraShake`
|
|
1003
1020
|
|
|
1004
1021
|
| Prop | Default | Kind |
|