incanto 0.21.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/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-Dt44Z9ka.js"></script>
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incanto",
3
- "version": "0.21.0",
3
+ "version": "0.22.0",
4
4
  "description": "Vibe-coding-first web game engine SDK — JSON-driven scenes on three.js",
5
5
  "keywords": [
6
6
  "game-engine",
@@ -766,6 +766,28 @@ plane and samples it per fragment, so those things appear in the water:
766
766
  - Geometry below the waterline is clipped out of the mirror pass, and the whole
767
767
  pass is skipped while the camera is submerged.
768
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
+
769
791
  ### Character interaction — `entered(body)` / `exited(body)`
770
792
 
771
793
  With `interaction: true` the water scans the tree each frame for
@@ -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, or spawning — BEFORE hand-rolling them as custom 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), 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,
@@ -1001,6 +1001,21 @@ Ready-made `Behavior`s auto-registered by `createGame2D`/`createGame3D` (opt out
1001
1001
  with `gameplay: false`). Attach via `"script": {"name": "...", "props": {...}}` and
1002
1002
  wire their signals through scene `connections`. Full guide: `incanto-gameplay-behaviors.md`.
1003
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
+
1004
1019
  ### `CameraShake`
1005
1020
 
1006
1021
  | Prop | Default | Kind |
@@ -14,7 +14,7 @@
14
14
  "@dimforge/rapier2d-compat": "0.19.3",
15
15
  "@dimforge/rapier3d-compat": "0.19.3",
16
16
  "@pixiv/three-vrm": "^3.5.3",
17
- "incanto": "^0.21.0",
17
+ "incanto": "^0.22.0",
18
18
  "three": "^0.184.0"
19
19
  },
20
20
  "devDependencies": {
@@ -13,7 +13,7 @@
13
13
  "@dimforge/rapier2d-compat": "0.19.3",
14
14
  "@dimforge/rapier3d-compat": "0.19.3",
15
15
  "@pixiv/three-vrm": "^3.5.3",
16
- "incanto": "^0.21.0",
16
+ "incanto": "^0.22.0",
17
17
  "three": "^0.184.0"
18
18
  },
19
19
  "devDependencies": {
@@ -13,7 +13,7 @@
13
13
  "@dimforge/rapier2d-compat": "0.19.3",
14
14
  "@dimforge/rapier3d-compat": "0.19.3",
15
15
  "@pixiv/three-vrm": "^3.5.3",
16
- "incanto": "^0.21.0",
16
+ "incanto": "^0.22.0",
17
17
  "three": "^0.184.0"
18
18
  },
19
19
  "devDependencies": {