incanto 0.69.0 → 0.71.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/bin/_behaviors-loader.mjs +22 -0
- package/bin/_read-json.mjs +28 -0
- package/bin/incanto-assets.mjs +5 -4
- package/bin/incanto-check.mjs +58 -31
- package/bin/incanto-editor.mjs +128 -5
- package/bin/incanto-env.mjs +3 -2
- package/bin/incanto-feel.mjs +24 -13
- package/bin/incanto-frame.mjs +8 -1
- package/bin/incanto-multiplay.mjs +11 -9
- package/bin/incanto-new.mjs +105 -10
- package/bin/incanto-play.mjs +158 -16
- package/bin/incanto-playtest.mjs +66 -23
- package/bin/incanto-skills.mjs +14 -2
- package/bin/incanto-verify.mjs +121 -102
- package/bin/incanto.mjs +3 -2
- package/dist/2d.d.ts +296 -34
- package/dist/2d.js +4 -4
- package/dist/3d.d.ts +157 -9
- package/dist/3d.js +8 -8
- package/dist/{agent8-CvsfVskX.js → agent8-Cfmd3ar_.js} +61 -8
- package/dist/{audio-player-C0j2k-yB.d.ts → audio-player-L8yccdMP.d.ts} +2 -2
- package/dist/{behavior-rm8vVzu_.d.ts → behavior-Dcz0fr1S.d.ts} +755 -46
- package/dist/{create-game-CwxEDlCm.js → create-game-CH4kt78v.js} +143 -60
- package/dist/{create-game-CvJ1wSRP.js → create-game-LCHBLfA4.js} +98 -48
- package/dist/debug.d.ts +1 -1
- package/dist/debug.js +2 -3
- package/dist/diagnostics-Cu85N3tL.d.ts +12 -0
- package/dist/{editor-switch-CnIOiyNJ.d.ts → editor-switch-CFU9mCec.d.ts} +22 -13
- package/dist/editor.js +1088 -882
- package/dist/env.d.ts +1 -1
- package/dist/env.js +5 -3
- package/dist/{environment-presets-BO-7XoFV.js → environment-presets-99BzP_L-.js} +298 -45
- package/dist/{frame-report-Dlq13Gyj.js → frame-report-D-_7YF2G.js} +1 -1
- package/dist/{gameplay-D1KixWK8.js → gameplay-CNULJvwh.js} +914 -214
- package/dist/gameplay.d.ts +254 -10
- package/dist/gameplay.js +2 -2
- package/dist/{heightmap-CRK0M4jT.js → heightmap-BYgD5Edk.js} +1 -1
- package/dist/index.d.ts +179 -13
- package/dist/index.js +10 -12
- package/dist/json-CfTjpvW8.js +67 -0
- package/dist/{loader-DadV2QCT.d.ts → loader-8-IHvbKD.d.ts} +2 -2
- package/dist/net.d.ts +27 -3
- package/dist/net.js +2 -2
- package/dist/{noise-CGUMx44x.js → noise-D3nPpmFg.js} +1 -1
- package/dist/{physics-2d-CF5yyjbj.js → physics-2d-FhrXUc6B.js} +136 -11
- package/dist/{physics-3d-DbYaEcZy.js → physics-3d-CFEGxBXZ.js} +104 -23
- package/dist/{teardown-CMqFVxO9.js → picking-DVo7fI13.js} +104 -13
- package/dist/react.d.ts +2 -2
- package/dist/react.js +2 -2
- package/dist/{register-DbVArsns.js → register-BYQCBySi.js} +429 -28
- package/dist/{register-mmfugpaQ.js → register-DuVdzxbq.js} +594 -831
- package/dist/{replay-BEHLDcQV.js → replay-DEvp3kyV.js} +224 -14
- package/dist/{replay-BQfkX4x7.d.ts → replay-F7IZHdFR.d.ts} +20 -3
- package/dist/{schema-B6ugCV1Q.d.ts → rng-Bb-IutXB.d.ts} +38 -21
- package/dist/{rng-DP-SR7eg.js → rng-CDOMybym.js} +22 -0
- package/dist/{loader-DZE7B07H.js → save-slots-Bvuh2p_r.js} +4619 -2318
- package/dist/{split-screen-Cg76MCV5.d.ts → split-screen-CIYf1zSf.d.ts} +36 -4
- package/dist/{split-screen-CauMwu6y.js → split-screen-eULetcg-.js} +159 -26
- package/dist/{sprite-animation-CY-mrr1L.js → sprite-animation-CqR2o3SA.js} +39 -8
- package/dist/{src-CYEu-_S9.js → src-_jk0qLsS.js} +2 -17
- package/dist/test-CmN54kWv.js +4264 -0
- package/dist/test.d.ts +639 -30
- package/dist/test.js +3 -3
- package/dist/touch-BnCyPA0G.js +519 -0
- package/dist/vite.d.ts +20 -37
- package/dist/vite.js +177 -7
- package/dist/{webgl-unavailable-Z5_g8x9H.js → webgl-unavailable-C8aDbGmR.js} +44 -0
- package/editor/assets/agent8-yLIEYHbd.js +1 -0
- package/editor/assets/{debug-CMULinBW.js → debug-u31w_yhq.js} +2 -2
- package/editor/assets/index-DK9xMGpW.js +11046 -0
- package/editor/index.html +1 -1
- package/package.json +4 -14
- package/schemas/scene.schema.json +34 -3
- package/skills/incanto-3d-character.md +14 -1
- package/skills/incanto-3d-models.md +12 -0
- package/skills/incanto-assets.md +9 -1
- package/skills/incanto-audio.md +8 -2
- package/skills/incanto-behaviors-and-scripts.md +105 -7
- package/skills/incanto-building-2d-games.md +97 -10
- package/skills/incanto-building-3d-games.md +58 -4
- package/skills/incanto-editor.md +46 -7
- package/skills/incanto-environment.md +19 -1
- package/skills/incanto-game-feel.md +70 -0
- package/skills/incanto-gameplay-behaviors.md +172 -20
- package/skills/incanto-hud.md +142 -7
- package/skills/incanto-localization.md +13 -5
- package/skills/incanto-multiplayer.md +83 -3
- package/skills/incanto-node-reference.md +239 -59
- package/skills/incanto-performance.md +52 -0
- package/skills/incanto-physics-and-input.md +123 -24
- package/skills/incanto-playtesting.md +112 -2
- package/skills/incanto-save-slots.md +217 -7
- package/skills/incanto-scene-json-authoring.md +69 -12
- package/skills/incanto-verifying-your-game.md +207 -10
- package/skills/incanto-web-integration.md +28 -0
- package/skills/incanto-your-first-game.md +3 -1
- package/templates-app/beacon-isle-3d/generate-world.ts +77 -9
- package/templates-app/beacon-isle-3d/package.json +2 -2
- package/templates-app/beacon-isle-3d/src/behaviors.ts +22 -0
- package/templates-app/beacon-isle-3d/src/game.scene.json +143 -600
- package/templates-app/beacon-isle-3d/src/main.ts +11 -1
- package/templates-app/beacon-isle-3d/tsconfig.json +1 -1
- package/templates-app/beacon-isle-3d/verify.ts +3 -1
- package/templates-app/molehill-2d/.incanto/playtest/lost-seed1.json +4277 -0
- package/templates-app/molehill-2d/PROJECT/Context.md +58 -0
- package/templates-app/molehill-2d/PROJECT/Requirements.md +39 -0
- package/templates-app/molehill-2d/PROJECT/Status.md +27 -0
- package/templates-app/molehill-2d/PROJECT/Structure.md +48 -0
- package/templates-app/molehill-2d/docs/project-2d-rules.md +44 -0
- package/templates-app/molehill-2d/index.html +73 -0
- package/templates-app/molehill-2d/package.json +23 -0
- package/templates-app/molehill-2d/src/behaviors.ts +198 -0
- package/templates-app/molehill-2d/src/game.scene.json +1205 -0
- package/templates-app/molehill-2d/src/main.ts +41 -0
- package/templates-app/molehill-2d/tsconfig.json +13 -0
- package/templates-app/molehill-2d/verify.ts +247 -0
- package/templates-app/molehill-2d/vite.config.ts +12 -0
- package/templates-app/platformer-2d/package.json +2 -2
- package/templates-app/platformer-2d/src/game.scene.json +178 -986
- package/templates-app/platformer-2d/src/main.ts +11 -1
- package/templates-app/platformer-2d/tsconfig.json +1 -1
- package/templates-app/star-survivor/package.json +2 -2
- package/templates-app/star-survivor/src/game.scene.json +43 -216
- package/templates-app/star-survivor/src/main.ts +11 -1
- package/templates-app/star-survivor/tsconfig.json +1 -1
- package/templates-app/tps-3d/PROJECT/Context.md +1 -1
- package/templates-app/tps-3d/package.json +2 -2
- package/templates-app/tps-3d/src/behaviors.ts +19 -1
- package/templates-app/tps-3d/src/game.scene.json +66 -263
- package/templates-app/tps-3d/src/main.ts +13 -2
- package/templates-app/tps-3d/tsconfig.json +1 -1
- package/templates-app/village-quest-3d/.incanto/playtest/swapped-seed1.json +1735 -0
- package/templates-app/village-quest-3d/package.json +2 -2
- package/templates-app/village-quest-3d/src/behaviors.ts +42 -4
- package/templates-app/village-quest-3d/src/grove.scene.json +68 -306
- package/templates-app/village-quest-3d/src/main.ts +11 -1
- package/templates-app/village-quest-3d/src/village.scene.json +202 -863
- package/templates-app/village-quest-3d/tsconfig.json +1 -1
- package/templates-app/village-quest-3d/verify.ts +14 -1
- package/dist/duplicate-Dj4L-5AA.js +0 -22
- package/dist/json-CwwhxQgb.js +0 -36
- package/dist/registry-CF70EArN.js +0 -212
- package/dist/rolldown-runtime-D7D4PA-g.js +0 -13
- package/dist/test-D6ISmuFE.js +0 -2383
- package/dist/touch-DEAmqGdf.js +0 -225
- package/editor/assets/agent8-BDvaZMQJ.js +0 -1
- package/editor/assets/index-CZIRr5EL.js +0 -10958
package/dist/2d.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { c as showBootFailure, i as ParticleSim, o as ParticleView, r as SpatialPose, s as isWebGLAvailable } from "./audio-player-
|
|
2
|
-
import { P as Scene$1, S as Scheduler, T as RendererStats, b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, w as GameStats, x as EngineOptions } from "./behavior-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { c as showBootFailure, i as ParticleSim, o as ParticleView, r as SpatialPose, s as isWebGLAvailable } from "./audio-player-L8yccdMP.js";
|
|
2
|
+
import { P as Scene$1, S as Scheduler, T as RendererStats, b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, w as GameStats, x as EngineOptions } from "./behavior-Dcz0fr1S.js";
|
|
3
|
+
import { t as DiagnosticSink } from "./diagnostics-Cu85N3tL.js";
|
|
4
|
+
import { a as SceneJson, s as JsonObject } from "./rng-Bb-IutXB.js";
|
|
5
|
+
import { t as EditorSwitchOptions } from "./editor-switch-CFU9mCec.js";
|
|
5
6
|
import { r as FrameStats } from "./frame-report-DNxDAb1w.js";
|
|
6
|
-
import { t as LoadSceneOptions } from "./loader-
|
|
7
|
+
import { t as LoadSceneOptions } from "./loader-8-IHvbKD.js";
|
|
7
8
|
import { n as AnimationEntry } from "./sprite-animation-CMr6f1K2.js";
|
|
8
9
|
import { Group, Mesh, Object3D, Scene, Texture } from "three";
|
|
9
10
|
import * as RapierNs from "@dimforge/rapier2d-compat";
|
|
@@ -53,6 +54,17 @@ declare class AssetStore2D {
|
|
|
53
54
|
/** Load status of a declared asset KEY (no '$'), or undefined if unknown. */
|
|
54
55
|
status(key: string): AssetStatus | undefined;
|
|
55
56
|
getTexture(ref: string): Texture;
|
|
57
|
+
/**
|
|
58
|
+
* Hand the GPU back.
|
|
59
|
+
*
|
|
60
|
+
* `AssetStore3D` has had this since it was written and the 2D twin never got
|
|
61
|
+
* one, so a game that swapped scenes or unmounted kept every texture it had
|
|
62
|
+
* ever decoded. `Renderer2D.dispose` walked its scene graph and disposed
|
|
63
|
+
* `material.map` instead — which frees only what is CURRENTLY drawn (a sheet
|
|
64
|
+
* loaded and never used stayed resident), and disposes the STORE'S texture
|
|
65
|
+
* out from under a caller who injected their own store.
|
|
66
|
+
*/
|
|
67
|
+
dispose(): void;
|
|
56
68
|
getSheet(ref: string): SheetInfo;
|
|
57
69
|
private resolve;
|
|
58
70
|
}
|
|
@@ -161,7 +173,7 @@ declare class Area2D extends PhysicsBody2D {
|
|
|
161
173
|
* Who is inside RIGHT NOW — the standing answer behind the enter/exit pair.
|
|
162
174
|
* See `Area3D.overlapping`. Empty in a scene with no physics world.
|
|
163
175
|
*/
|
|
164
|
-
overlapping(group?: string): PhysicsBody2D[];
|
|
176
|
+
overlapping(group?: string | undefined): PhysicsBody2D[];
|
|
165
177
|
}
|
|
166
178
|
/** Dynamic simulated body. */
|
|
167
179
|
declare class RigidBody2D extends PhysicsBody2D {
|
|
@@ -174,6 +186,38 @@ declare class RigidBody2D extends PhysicsBody2D {
|
|
|
174
186
|
restitution: number;
|
|
175
187
|
/** px/s, y-down. Read back every step; write to launch. */
|
|
176
188
|
linearVelocity: number[];
|
|
189
|
+
/**
|
|
190
|
+
* rad/s about the z axis — the same sign as `rotation`, which is CLOCKWISE
|
|
191
|
+
* in this y-down space. Read back every step; write to spin.
|
|
192
|
+
*
|
|
193
|
+
* `RigidBody3D` got its `angularVelocity` because "a puzzle builder could
|
|
194
|
+
* neither launch a spinning body nor read how fast a lever was swinging —
|
|
195
|
+
* only its angle, differenced by hand". Same sentence, same defect, other
|
|
196
|
+
* adapter: 2D had `linearVelocity` and no counterpart. `fixedRotation` pins
|
|
197
|
+
* it at zero.
|
|
198
|
+
*/
|
|
199
|
+
angularVelocity: number;
|
|
200
|
+
/**
|
|
201
|
+
* The other name for `linearVelocity`, because it is the name every skill,
|
|
202
|
+
* every sibling node and every other engine uses.
|
|
203
|
+
*
|
|
204
|
+
* `body.velocity = [0, -400]` is what `incanto-physics-and-input.md` taught
|
|
205
|
+
* for years. On a plain TS class that assignment SUCCEEDS — it just writes a
|
|
206
|
+
* stray field nothing reads — so a jump that never happened produced no
|
|
207
|
+
* error, no warning and nothing to search for. `CharacterBody2D.velocity`
|
|
208
|
+
* next to `RigidBody2D.linearVelocity` is the kind of near-miss a builder
|
|
209
|
+
* cannot be expected to notice.
|
|
210
|
+
*
|
|
211
|
+
* Scene JSON still names the prop `linearVelocity` and rejects `velocity`
|
|
212
|
+
* loudly, with the valid keys listed — a hard error corrects itself.
|
|
213
|
+
*/
|
|
214
|
+
get velocity(): number[];
|
|
215
|
+
set velocity(v: number[]);
|
|
216
|
+
/**
|
|
217
|
+
* Impulse in px·kg/s (y-down) — the 3D twin has had this since it shipped,
|
|
218
|
+
* and calling it here was a TypeError.
|
|
219
|
+
*/
|
|
220
|
+
applyImpulse(impulse: [number, number]): void;
|
|
177
221
|
}
|
|
178
222
|
/**
|
|
179
223
|
* Kinematic body on Rapier's character controller. Gravity is NOT applied
|
|
@@ -195,6 +239,17 @@ declare class CharacterBody2D extends PhysicsBody2D {
|
|
|
195
239
|
stickToGround: boolean;
|
|
196
240
|
/** Max climbable slope angle. */
|
|
197
241
|
slopeLimitDeg: number;
|
|
242
|
+
/**
|
|
243
|
+
* How high a step this body walks up without jumping, in PIXELS.
|
|
244
|
+
*
|
|
245
|
+
* Rapier's character controller does not autostep unless it is asked, and in
|
|
246
|
+
* 2D nothing asked: a ledge of ANY height — measured, ONE pixel — stopped a
|
|
247
|
+
* walking body dead, while the mirrored `CharacterBody3D` has cleared 0.35 m
|
|
248
|
+
* by default since 0.63. The default here is that same 0.35 m at the 2D
|
|
249
|
+
* world's own scale (100 px = 1 m, which is why gravity defaults to 980).
|
|
250
|
+
* `0` restores the old behaviour.
|
|
251
|
+
*/
|
|
252
|
+
stepHeight: number;
|
|
198
253
|
/** @internal Updated by Physics2D.moveAndSlide. */
|
|
199
254
|
_grounded: boolean;
|
|
200
255
|
moveAndSlide(): void;
|
|
@@ -263,6 +318,22 @@ declare class Physics2D {
|
|
|
263
318
|
/** Whether the solver runs at all. False = collider outlines only. */
|
|
264
319
|
private readonly simulate;
|
|
265
320
|
step(dt: number): void;
|
|
321
|
+
/**
|
|
322
|
+
* May `candidate` carry `rider`?
|
|
323
|
+
*
|
|
324
|
+
* The rule used to be "never a CharacterBody2D", which is the whole CLASS —
|
|
325
|
+
* and a `CharacterBody2D` animated by POSITION WRITES is the documented
|
|
326
|
+
* moving-platform path (`Oscillate`, `MoveTo`, `PathFollow`, or a behaviour of
|
|
327
|
+
* your own). `incanto-physics-and-input.md` promises twice that a character
|
|
328
|
+
* standing on ANY moving body is carried; it was not, and the rider reported
|
|
329
|
+
* `isOnFloor() === true` the whole time while sliding off in world space.
|
|
330
|
+
*
|
|
331
|
+
* What the guard was really for is a CYCLE: two characters standing on each
|
|
332
|
+
* other would carry each other forever. So the test is the rider's own
|
|
333
|
+
* carrier chain, not the type — a platform that is not (transitively) riding
|
|
334
|
+
* you can carry you.
|
|
335
|
+
*/
|
|
336
|
+
private canCarry;
|
|
266
337
|
/** @internal Called by CharacterBody2D.moveAndSlide (during tree fixedUpdate). */
|
|
267
338
|
moveAndSlide(node: CharacterBody2D): void;
|
|
268
339
|
/** Rapier debug segments, scaled back to pixels. Null while debugDraw is off. */
|
|
@@ -292,7 +363,31 @@ declare class Physics2D {
|
|
|
292
363
|
/** The bodies currently overlapping `node`. Freed nodes are dropped on read. */
|
|
293
364
|
overlapping(node: PhysicsBody2D): PhysicsBody2D[];
|
|
294
365
|
/**
|
|
295
|
-
*
|
|
366
|
+
* Mass the solver actually uses (collider-derived unless overridden).
|
|
367
|
+
*
|
|
368
|
+
* The 3D twin has had this since `CharacterController3D` needed it to size an
|
|
369
|
+
* impulse; 2D had no way to ask, so a 2D game scaling a push by mass had to
|
|
370
|
+
* read the AUTHORED `mass` prop and hope it was the number Rapier settled on.
|
|
371
|
+
*/
|
|
372
|
+
massOf(node: PhysicsBody2D): number;
|
|
373
|
+
/**
|
|
374
|
+
* Current solver velocity in px/s (fresher than the node prop mid-step).
|
|
375
|
+
*
|
|
376
|
+
* `linearVelocity` is written back once per step, so a behavior reading it
|
|
377
|
+
* from inside `fixedUpdate` — after a collision, before the write-back — sees
|
|
378
|
+
* the value from BEFORE the impact. That is exactly when a game wants to know
|
|
379
|
+
* how hard it hit something.
|
|
380
|
+
*/
|
|
381
|
+
velocityOf(node: PhysicsBody2D): [number, number];
|
|
382
|
+
/**
|
|
383
|
+
* A world-space impulse in px.kg/s (y-down) — the 2D twin of
|
|
384
|
+
* `Physics3D.applyImpulse`, which the physics skill has documented for both
|
|
385
|
+
* adapters while only one of them had it.
|
|
386
|
+
*/
|
|
387
|
+
applyImpulse(node: PhysicsBody2D, impulse: [number, number]): void;
|
|
388
|
+
/**
|
|
389
|
+
* World-space raycast in PIXELS (y-down); `dir` may be any length (it is
|
|
390
|
+
* normalized), so `distance` and `maxLen` are pixels. `exclude` skips that body — a
|
|
296
391
|
* shooter probing from inside its own collider needs it. Sensors (Area2D)
|
|
297
392
|
* never block rays. Returns distance (px), the surface normal, and the hit
|
|
298
393
|
* body — or null.
|
|
@@ -303,6 +398,27 @@ declare class Physics2D {
|
|
|
303
398
|
distance: number;
|
|
304
399
|
normal: [number, number];
|
|
305
400
|
node: PhysicsBody2D | null;
|
|
401
|
+
point: [number, number];
|
|
402
|
+
} | null;
|
|
403
|
+
/**
|
|
404
|
+
* Sweep a CIRCLE of `radius` from `origin` along `dir` — a thick ray, in
|
|
405
|
+
* pixels. The 2D twin of `Physics3D.castSphere`.
|
|
406
|
+
*
|
|
407
|
+
* 3D has had this since the camera spring arm needed it and 2D never got it,
|
|
408
|
+
* so the shared `PhysicsQuery` interface declares it OPTIONAL and every 2D
|
|
409
|
+
* game that wanted a probe with THICKNESS — a shot that must not thread a
|
|
410
|
+
* one-pixel gap between two tiles, a ledge feeler, a camera that should not
|
|
411
|
+
* clip a wall it skims — had to fire several thin rays and hope.
|
|
412
|
+
*
|
|
413
|
+
* Same filters as `castRay`: sensors never hit, `staticOnly` ignores dynamic
|
|
414
|
+
* and kinematic bodies, `dir` may be any length. Returns the travel distance
|
|
415
|
+
* of the circle's CENTRE, or null when the sweep is clear.
|
|
416
|
+
*/
|
|
417
|
+
castSphere(origin: [number, number], dir: [number, number], radius: number, maxLen: number, exclude?: PhysicsBody2D, opts?: {
|
|
418
|
+
staticOnly?: boolean;
|
|
419
|
+
}): {
|
|
420
|
+
distance: number;
|
|
421
|
+
node: PhysicsBody2D | null;
|
|
306
422
|
} | null;
|
|
307
423
|
dispose(): void;
|
|
308
424
|
private lastStructure;
|
|
@@ -357,6 +473,14 @@ interface CreateGame2DOptions {
|
|
|
357
473
|
* Attach pointer input (mouse, finger or pen) to the canvas: positions for
|
|
358
474
|
* `input.pointerPosition()`, buttons for `input.mousePressed()`.
|
|
359
475
|
* `{ lockOnClick: true }` captures the cursor — rare in 2D, so it is off.
|
|
476
|
+
*
|
|
477
|
+
* Omitted, it is AUTO: attached when the scene contains a `Clickable`, the
|
|
478
|
+
* same way `physics: 'auto'` turns Rapier on for a scene with bodies. It used
|
|
479
|
+
* to default OFF, so a board of clickable tiles did nothing when clicked —
|
|
480
|
+
* with no error, a clean `incanto-check` and a clean audit, while the skill
|
|
481
|
+
* that introduces the behaviour says it "needs no code at all". Pass `true`
|
|
482
|
+
* when a behaviour of your own reads `pointerPosition()`; nothing here can
|
|
483
|
+
* see that.
|
|
360
484
|
*/
|
|
361
485
|
pointer?: boolean | {
|
|
362
486
|
lockOnClick?: boolean;
|
|
@@ -412,6 +536,20 @@ interface CreateGame2DOptions {
|
|
|
412
536
|
/** Renderer extras (pixelRatio, antialias, custom asset store). */
|
|
413
537
|
pixelRatio?: number;
|
|
414
538
|
antialias?: boolean;
|
|
539
|
+
/**
|
|
540
|
+
* Keep the drawing buffer readable so the canvas can be screenshot.
|
|
541
|
+
*
|
|
542
|
+
* WebGL clears it the instant a frame composites, so `toDataURL()` — and
|
|
543
|
+
* every screenshot built on it — is BLANK without this. Off by default: it
|
|
544
|
+
* costs a buffer copy per frame and only a run that means to look at the
|
|
545
|
+
* output should pay for it. `environment.rendering.preserveDrawingBuffer`
|
|
546
|
+
* does the same from the scene.
|
|
547
|
+
*
|
|
548
|
+
* The 2D renderer has always honoured the scene key; only the boot-site
|
|
549
|
+
* override was 3D-only, so a 2D game whose harness wanted a screenshot had to
|
|
550
|
+
* edit its scene file to get one.
|
|
551
|
+
*/
|
|
552
|
+
preserveDrawingBuffer?: boolean;
|
|
415
553
|
resolveScene?: LoadSceneOptions["resolveScene"];
|
|
416
554
|
/** @internal Test seam — replaces the Renderer2D construction. */
|
|
417
555
|
_rendererFactory?: (engine: Engine, canvas: HTMLCanvasElement) => GameRenderer;
|
|
@@ -569,6 +707,18 @@ declare class Sprite2D extends Node2D {
|
|
|
569
707
|
protected resolveTexture(assets: AssetStore2D | null): ResolvedSpriteTexture | null;
|
|
570
708
|
override _staticReady(assets: AssetStore2D | null): boolean;
|
|
571
709
|
override _syncObject2D(assets: AssetStore2D | null): void;
|
|
710
|
+
/**
|
|
711
|
+
* The material is PER NODE and nothing freed it.
|
|
712
|
+
*
|
|
713
|
+
* The geometry is shared for the process (`UNIT_PLANE`, on purpose), but
|
|
714
|
+
* every sprite makes its own `MeshBasicMaterial` — and a 2D game that spawns
|
|
715
|
+
* and frees sprites, which is every 2D game, leaked one per node forever.
|
|
716
|
+
* The TEXTURE is not touched: it belongs to the asset store and is shared by
|
|
717
|
+
* every node that names the same key.
|
|
718
|
+
*
|
|
719
|
+
* `AnimatedSprite2D` extends this, so it is covered by the same override.
|
|
720
|
+
*/
|
|
721
|
+
override free(): void;
|
|
572
722
|
}
|
|
573
723
|
//#endregion
|
|
574
724
|
//#region src/2d/nodes/animated-sprite-2d.d.ts
|
|
@@ -636,6 +786,8 @@ declare class Camera2D extends Node2D {
|
|
|
636
786
|
current: boolean;
|
|
637
787
|
/** `zoom` clamped to a positive floor — 0/negative zoom must never produce NaN views. */
|
|
638
788
|
get effectiveZoom(): number;
|
|
789
|
+
/** The `follow` path already reported as untrackable — cleared by a new one. */
|
|
790
|
+
private warnedFollow;
|
|
639
791
|
override update(dt: number): void;
|
|
640
792
|
/** View center after clamping the (vw×vh)/zoom view rect inside `limits`. */
|
|
641
793
|
/**
|
|
@@ -663,26 +815,6 @@ declare class Camera2D extends Node2D {
|
|
|
663
815
|
}
|
|
664
816
|
//#endregion
|
|
665
817
|
//#region src/2d/nodes/character-controller-2d.d.ts
|
|
666
|
-
/**
|
|
667
|
-
* Preset controller: drives its PARENT CharacterBody2D from the engine
|
|
668
|
-
* InputMap — JSON-only games get a playable character with zero TypeScript.
|
|
669
|
-
*
|
|
670
|
-
* - `platformer`: x movement + gravity (from the scene `physics.gravity[1]`,
|
|
671
|
-
* default 980) + jump (`jumpHeight` px → impulse √(2·g·h))
|
|
672
|
-
* - `topDown`: full-axis movement, no gravity
|
|
673
|
-
*
|
|
674
|
-
* ## Why the extra platformer props exist
|
|
675
|
-
*
|
|
676
|
-
* A jump that only works while `isOnFloor()` is true feels BROKEN, and players
|
|
677
|
-
* do not report it as "the coyote time is missing" — they report the game as
|
|
678
|
-
* unresponsive. The whole schema used to be five props, so a JSON-only game got
|
|
679
|
-
* a character that felt wrong and could not drive `AnimatedSprite2D.play('run')`
|
|
680
|
-
* either. `examples/platformer-2d` hand-rolls all of this in a 541-line
|
|
681
|
-
* behavior; these are those constants, as props.
|
|
682
|
-
*
|
|
683
|
-
* Every one defaults to OFF (0 / 1 / false), so an existing scene behaves
|
|
684
|
-
* exactly as before until it asks for something.
|
|
685
|
-
*/
|
|
686
818
|
declare class CharacterController2D extends Node {
|
|
687
819
|
static override readonly typeName: string;
|
|
688
820
|
static readonly props: PropSchema;
|
|
@@ -718,6 +850,29 @@ declare class CharacterController2D extends Node {
|
|
|
718
850
|
* from scene JSON instead of a behavior polling velocities.
|
|
719
851
|
*/
|
|
720
852
|
private setState;
|
|
853
|
+
/** Actions already reported missing, so a per-frame read says it once. */
|
|
854
|
+
private readonly reportedActions;
|
|
855
|
+
/**
|
|
856
|
+
* Read an input action this controller is allowed to be missing.
|
|
857
|
+
*
|
|
858
|
+
* The 3D controller has done this since `optional-action.ts` was written —
|
|
859
|
+
* whose own docstring says "`CharacterController3D` and `GameFlow` wrap every
|
|
860
|
+
* input read" — and the 2D one did not. So a top-down 2D game, which is the
|
|
861
|
+
* first thing anyone builds with this node and has no jump key, declared
|
|
862
|
+
* `move` and got:
|
|
863
|
+
*
|
|
864
|
+
* ```
|
|
865
|
+
* [incanto] /Game/Player/Ctl (CharacterController2D) threw in fixedUpdate —
|
|
866
|
+
* this node is now SKIPPED. IncantoError: Unknown input action 'jump'.
|
|
867
|
+
* Declared actions: [move].
|
|
868
|
+
* ```
|
|
869
|
+
*
|
|
870
|
+
* SKIPPED: the character could not move either, and every tool reported the
|
|
871
|
+
* game as `✗ error in 1/1` with the reason only in the log. Tolerated because
|
|
872
|
+
* a game with no jump key is the ordinary case; reported because otherwise a
|
|
873
|
+
* TYPO in `"jumpAction"` looks exactly like a deliberate omission.
|
|
874
|
+
*/
|
|
875
|
+
private readAction;
|
|
721
876
|
}
|
|
722
877
|
//#endregion
|
|
723
878
|
//#region src/2d/nodes/color-rect-2d.d.ts
|
|
@@ -739,6 +894,20 @@ declare class ColorRect2D extends Node2D {
|
|
|
739
894
|
/** @internal The drawable quad (lazily created under the backing object). */
|
|
740
895
|
_quad(): Mesh;
|
|
741
896
|
override _syncObject2D(assets: AssetStore2D | null): void;
|
|
897
|
+
/**
|
|
898
|
+
* The material is PER NODE and nothing freed it.
|
|
899
|
+
*
|
|
900
|
+
* The geometry is shared for the process (`UNIT_PLANE`, on purpose — a
|
|
901
|
+
* `THREE.Sprite` cannot be instanced and this is the discipline that replaces
|
|
902
|
+
* it), but every rect makes its own `MeshBasicMaterial`, and a 2D game that
|
|
903
|
+
* spawns and frees — bullets, coins, damage flashes, a level swap — leaks one
|
|
904
|
+
* GPU program's worth of state per node, forever.
|
|
905
|
+
*
|
|
906
|
+
* Four 3D nodes had exactly this and were fixed. These two 2D siblings make a
|
|
907
|
+
* material on the same line of the same kind of `_quad()` helper, and were
|
|
908
|
+
* not on that list.
|
|
909
|
+
*/
|
|
910
|
+
override free(): void;
|
|
742
911
|
}
|
|
743
912
|
//#endregion
|
|
744
913
|
//#region src/2d/nodes/joint-2d.d.ts
|
|
@@ -982,6 +1151,21 @@ declare class TileMap2D extends Node2D {
|
|
|
982
1151
|
set cells(value: (string | number[])[]);
|
|
983
1152
|
get legend(): Record<string, number>;
|
|
984
1153
|
set legend(value: Record<string, number>);
|
|
1154
|
+
private _colors;
|
|
1155
|
+
get colors(): Record<string, string>;
|
|
1156
|
+
set colors(value: Record<string, string>);
|
|
1157
|
+
/**
|
|
1158
|
+
* The colours, in declaration order — a cell's tile index is `COLOR_BASE + i`.
|
|
1159
|
+
*
|
|
1160
|
+
* A synthetic index rather than a second grid: everything downstream (the
|
|
1161
|
+
* collider merge, `tileAt`, `setTile`, the editor's paint tool) already
|
|
1162
|
+
* speaks in indices, and one number per cell keeps it that way.
|
|
1163
|
+
*/
|
|
1164
|
+
private palette;
|
|
1165
|
+
/** `legend` plus the colour chars, which is what every cell lookup wants. */
|
|
1166
|
+
private allChars;
|
|
1167
|
+
/** `solid` as INDICES: an entry may name the char that painted the cell. */
|
|
1168
|
+
private solidIndices;
|
|
985
1169
|
get solid(): number[];
|
|
986
1170
|
set solid(value: number[]);
|
|
987
1171
|
opacity: number;
|
|
@@ -992,6 +1176,62 @@ declare class TileMap2D extends Node2D {
|
|
|
992
1176
|
static validateJson(node: Node): void;
|
|
993
1177
|
/** The parsed index grid (test/tooling hook). */
|
|
994
1178
|
grid(): number[][];
|
|
1179
|
+
/**
|
|
1180
|
+
* Which CELL is under this world point — `null` outside the grid.
|
|
1181
|
+
*
|
|
1182
|
+
* The one question a tile game asks constantly and this node could not
|
|
1183
|
+
* answer. `VoxelGrid3D`, the 3D grid, has had `tileAt` since it was written;
|
|
1184
|
+
* the 2D one shipped `grid()` and nothing else, so every mouse-driven tile
|
|
1185
|
+
* game hand-rolled the same arithmetic with the same two traps in it: cell
|
|
1186
|
+
* (0,0) hangs its TOP-LEFT on the origin (so a cell's CENTRE is half a tile
|
|
1187
|
+
* further on), and the origin is the node's WORLD position, not its `position`
|
|
1188
|
+
* prop.
|
|
1189
|
+
*
|
|
1190
|
+
* Composes ancestor POSITIONS, like every other world query in the engine
|
|
1191
|
+
* (`Terrain3D.heightAt`, `Water3D`); `auditScene` reports an ancestor that
|
|
1192
|
+
* scales or rotates one of these, because that moves the picture and not the
|
|
1193
|
+
* answer.
|
|
1194
|
+
*/
|
|
1195
|
+
cellAt(worldX: number, worldY: number): [number, number] | null;
|
|
1196
|
+
/**
|
|
1197
|
+
* One cell's size in WORLD pixels — `tileSize` times this node's own scale.
|
|
1198
|
+
*
|
|
1199
|
+
* `scale` is an ordinary `Node2D` prop, the renderer scales the mesh by it,
|
|
1200
|
+
* and `rebuildColliders` has always rebuilt when it changes — so at
|
|
1201
|
+
* `scale: [2, 2]` a tile is 64 px wide on screen AND in physics. These
|
|
1202
|
+
* queries divided by 32 and answered the wrong cell, in silence, which is the
|
|
1203
|
+
* picture and the collider agreeing and the decider disagreeing with both.
|
|
1204
|
+
*
|
|
1205
|
+
* Ancestor scale is not composed here, for the same reason `worldPosition`
|
|
1206
|
+
* does not: every world query in the engine reads its own props and composes
|
|
1207
|
+
* ancestor POSITIONS, and `auditScene` reports an ancestor that scales one.
|
|
1208
|
+
*/
|
|
1209
|
+
private scaledTile;
|
|
1210
|
+
/** The atlas index at a cell — `-1` for an empty cell or one off the grid. */
|
|
1211
|
+
tileAt(cx: number, cy: number): number;
|
|
1212
|
+
/**
|
|
1213
|
+
* The CENTRE of a cell, in world pixels — for putting a highlight, a marker
|
|
1214
|
+
* or a spawned enemy on a tile.
|
|
1215
|
+
*
|
|
1216
|
+
* The centre rather than the corner, because that is where a thing goes and
|
|
1217
|
+
* because the corner is the half-tile every hand-rolled version forgets.
|
|
1218
|
+
*/
|
|
1219
|
+
worldAt(cx: number, cy: number): [number, number];
|
|
1220
|
+
/**
|
|
1221
|
+
* Write ONE cell, by the character the row holds — dig a tile out, drop a
|
|
1222
|
+
* wall in, flip a switch.
|
|
1223
|
+
*
|
|
1224
|
+
* `cells` are strings and a mutation is not watched, so the documented way to
|
|
1225
|
+
* change a map was to rebuild the whole row by hand
|
|
1226
|
+
* (`row.slice(0, x) + c + row.slice(x + 1)`) and reassign the array. This is
|
|
1227
|
+
* that, once, correctly, and it rebuilds the geometry and the colliders.
|
|
1228
|
+
*
|
|
1229
|
+
* A CHARACTER, not an index: `legend` may map several characters to one tile,
|
|
1230
|
+
* so an index cannot say which of them you meant. `'.'` empties the cell.
|
|
1231
|
+
* Returns false for a cell off the grid, or a numeric row (those hold indices
|
|
1232
|
+
* — assign the row).
|
|
1233
|
+
*/
|
|
1234
|
+
setTile(cx: number, cy: number, char: string): boolean;
|
|
995
1235
|
override onReady(): void;
|
|
996
1236
|
override update(_dt: number): void;
|
|
997
1237
|
private rebuildColliders;
|
|
@@ -1070,6 +1310,12 @@ interface Renderer2DOptions {
|
|
|
1070
1310
|
pixelRatio?: number;
|
|
1071
1311
|
/** MSAA on the canvas. Defaults to TRUE (Phaser parity). */
|
|
1072
1312
|
antialias?: boolean;
|
|
1313
|
+
/**
|
|
1314
|
+
* Keep the drawing buffer readable so the canvas can be screenshot — see
|
|
1315
|
+
* `CreateGame2DOptions`. `environment.rendering.preserveDrawingBuffer` does
|
|
1316
|
+
* the same from the scene, and an explicit option here outranks it.
|
|
1317
|
+
*/
|
|
1318
|
+
preserveDrawingBuffer?: boolean;
|
|
1073
1319
|
}
|
|
1074
1320
|
declare class Renderer2D {
|
|
1075
1321
|
/**
|
|
@@ -1120,6 +1366,7 @@ declare class Renderer2D {
|
|
|
1120
1366
|
private readonly engine;
|
|
1121
1367
|
/** The texture store. Public so `renderer.assets.status(key)` is reachable. */
|
|
1122
1368
|
readonly assets: AssetStore2D;
|
|
1369
|
+
private readonly ownsAssets;
|
|
1123
1370
|
private readonly loadedAssetScenes;
|
|
1124
1371
|
private readonly disconnect;
|
|
1125
1372
|
private readonly canvas;
|
|
@@ -1132,7 +1379,29 @@ declare class Renderer2D {
|
|
|
1132
1379
|
/** UI-pass extent from the last render — the space HUD nodes are posed in. */
|
|
1133
1380
|
private lastUi;
|
|
1134
1381
|
private lastViewport;
|
|
1382
|
+
/**
|
|
1383
|
+
* The view the LAST render used — and, before there has been one, the
|
|
1384
|
+
* documented default: the whole canvas, centred, at zoom 1.
|
|
1385
|
+
*
|
|
1386
|
+
* It started as `{cx: 0, cy: 0, w: 1, h: 1}`, a one-pixel canvas nobody has,
|
|
1387
|
+
* and `worldFromScreen` answered from it with a straight face. Measured in a
|
|
1388
|
+
* browser on a 960x540 canvas with the camera at (160, 80), before the first
|
|
1389
|
+
* frame: `toWorld(480, 270)` returned `[479.5, 269.5]` — the arithmetic of a
|
|
1390
|
+
* 1x1 window, and a confident number rather than a refusal.
|
|
1391
|
+
*/
|
|
1135
1392
|
private lastView;
|
|
1393
|
+
/**
|
|
1394
|
+
* Has a frame been DRAWN?
|
|
1395
|
+
*
|
|
1396
|
+
* `Renderer3D` refuses every screen-space question until it has one
|
|
1397
|
+
* (`if (!this.lastCamera) return null`, in `pick`, `rayFromScreen` and
|
|
1398
|
+
* `worldFromScreen`); the flat renderer had no equivalent, so the engine-level
|
|
1399
|
+
* `toWorld`/`toScreen` and `pick` answered from a view no frame had used. The
|
|
1400
|
+
* hazard is real in exactly the place agents work: a background tab does not
|
|
1401
|
+
* run rAF, so `await createGame2D(...)` there is followed by any number of
|
|
1402
|
+
* questions with no frame behind them.
|
|
1403
|
+
*/
|
|
1404
|
+
private hasRendered;
|
|
1136
1405
|
/** The world view used by the LAST render (center/zoom/canvas size). */
|
|
1137
1406
|
view(): View2D;
|
|
1138
1407
|
/**
|
|
@@ -1234,13 +1503,6 @@ interface TileRect {
|
|
|
1234
1503
|
w: number;
|
|
1235
1504
|
h: number;
|
|
1236
1505
|
}
|
|
1237
|
-
/**
|
|
1238
|
-
* Normalize the `cells` prop into an index grid. Two author formats:
|
|
1239
|
-
* - string rows: `"." `/`" "` = empty, digits `0-9` = tile index, anything
|
|
1240
|
-
* else must be in `legend` (char → index). Unknown chars HARD-fail.
|
|
1241
|
-
* - number rows: passed through (`-1` = empty).
|
|
1242
|
-
* Ragged rows are right-padded with empty.
|
|
1243
|
-
*/
|
|
1244
1506
|
declare function parseCells(cells: readonly (string | readonly number[])[], legend: Record<string, number>): number[][];
|
|
1245
1507
|
/**
|
|
1246
1508
|
* Greedy rectangle merge over the solid cells: maximal horizontal runs,
|
package/dist/2d.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
2
2
|
import { t as showBootFailure } from "./boot-failure-CKYrEcGF.js";
|
|
3
|
-
import { t as isWebGLAvailable } from "./webgl-unavailable-
|
|
4
|
-
import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-
|
|
5
|
-
import { _ as RigidBody2D, a as parseCells, c as ColorRect2D, d as AnimatedSprite2D, f as Sprite2D, g as PhysicsBody2D, h as CharacterBody2D, i as mergeSolidRects, l as CharacterController2D, m as Area2D, n as UILayer, o as Particles2D, p as Joint2D, r as TileMap2D, s as Label, t as registerNodes2D, u as Camera2D, v as StaticBody2D, y as Node2D } from "./register-
|
|
6
|
-
import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-
|
|
3
|
+
import { t as isWebGLAvailable } from "./webgl-unavailable-C8aDbGmR.js";
|
|
4
|
+
import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-CH4kt78v.js";
|
|
5
|
+
import { _ as RigidBody2D, a as parseCells, c as ColorRect2D, d as AnimatedSprite2D, f as Sprite2D, g as PhysicsBody2D, h as CharacterBody2D, i as mergeSolidRects, l as CharacterController2D, m as Area2D, n as UILayer, o as Particles2D, p as Joint2D, r as TileMap2D, s as Label, t as registerNodes2D, u as Camera2D, v as StaticBody2D, y as Node2D } from "./register-BYQCBySi.js";
|
|
6
|
+
import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-FhrXUc6B.js";
|
|
7
7
|
//#region src/2d/library-sprite.ts
|
|
8
8
|
/**
|
|
9
9
|
* What a `CharacterController2D`/`3D` will ask a skin to play, and the clip in
|