incanto 0.31.0 → 0.33.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/incanto-play.mjs +7 -2
- package/dist/2d.d.ts +59 -2
- package/dist/2d.js +3 -3
- package/dist/3d.d.ts +28 -3
- package/dist/3d.js +4 -4
- package/dist/{behavior-D_jMpFh8.d.ts → behavior-CKwTCjfR.d.ts} +140 -1
- package/dist/{create-game-z5XaB1p5.js → create-game-D2QU5x7S.js} +16 -8
- package/dist/{create-game-DqOjMBUS.js → create-game-sFuTLqjD.js} +22 -10
- package/dist/debug.d.ts +1 -1
- package/dist/{duplicate-KRPtUtzl.js → duplicate-BgnG1Lqz.js} +1 -1
- package/dist/editor.js +35 -0
- package/dist/{environment-presets--DigHNg4.js → environment-presets-CQtEGogB.js} +2 -2
- package/dist/{gameplay-BftxM_It.js → gameplay-BpQCbABv.js} +90 -2
- package/dist/gameplay.d.ts +1 -1
- package/dist/gameplay.js +1 -1
- package/dist/index.d.ts +135 -23
- package/dist/index.js +6 -59
- package/dist/{loader-BlaRQGaA.js → loader-Buk8Bu1h.js} +53 -0
- package/dist/{loader-BYBrqTxP.d.ts → loader-COn5fS0o.d.ts} +1 -1
- package/dist/net.d.ts +1 -1
- package/dist/net.js +3 -3
- package/dist/{pathfinding-BwhqPD3i.d.ts → pathfinding-DUw9mir9.d.ts} +1 -1
- package/dist/{physics-2d-D9wquBvK.js → physics-2d-DjXR5DMu.js} +12 -2
- package/dist/{physics-3d-CnPygVGo.js → physics-3d-DF8npb1O.js} +55 -9
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-Dzkd6-os.js → register-CscIzJEO.js} +551 -13
- package/dist/{register-CUY284Is.js → register-CtI-itec.js} +2 -2
- package/dist/{register-tkR_8tWg.js → register-FIJtNbub.js} +145 -8
- package/dist/test-BRxLd2jH.js +642 -0
- package/dist/test.d.ts +55 -3
- package/dist/test.js +2 -392
- package/dist/{touch-031PxtCR.js → touch-BoNg_MnF.js} +2 -1
- package/dist/vite.js +1 -1
- package/editor/assets/{agent8-o27_Y1xN.js → agent8-BdDP3xKW.js} +1 -1
- package/editor/assets/{debug-DfcWX3uW.js → debug-DbjTyTlC.js} +1 -1
- package/editor/assets/{index-C9fb5QcT.js → index-BWCudoz1.js} +90 -90
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +520 -0
- package/skills/README.md +14 -2
- package/skills/incanto-audio.md +43 -0
- package/skills/incanto-building-2d-games.md +52 -0
- package/skills/incanto-building-3d-games.md +16 -0
- package/skills/incanto-hud.md +41 -0
- package/skills/incanto-node-reference.md +89 -0
- package/skills/incanto-physics-and-input.md +50 -0
- package/skills/incanto-verifying-your-game.md +86 -30
- package/templates-app/beacon-isle-3d/docs/project-3d-rules.md +40 -19
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/tps-3d/docs/project-3d-rules.md +41 -19
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/village-quest-3d/docs/project-3d-rules.md +40 -19
- package/templates-app/village-quest-3d/package.json +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { f as Node } from "./loader-
|
|
2
|
-
import { t as registerCoreNodes } from "./register-
|
|
1
|
+
import { f as Node } from "./loader-Buk8Bu1h.js";
|
|
2
|
+
import { t as registerCoreNodes } from "./register-CscIzJEO.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
4
|
import { t as Rng } from "./rng-DP-SR7eg.js";
|
|
5
5
|
import { i as getNodeSchema, l as registerNode } from "./registry-CJdGpT2V.js";
|
|
6
|
-
import { r as effectiveOrder } from "./duplicate-
|
|
6
|
+
import { r as effectiveOrder } from "./duplicate-BgnG1Lqz.js";
|
|
7
7
|
import { i as applyParticlePreset, r as PARTICLE_PRESET_NAMES, t as ParticleSim } from "./particle-sim-Bw7hB93B.js";
|
|
8
8
|
import { AdditiveBlending, BufferAttribute, BufferGeometry, CanvasTexture, Color, DynamicDrawUsage, Group, InstancedMesh, MathUtils, Matrix4, Mesh, MeshBasicMaterial, NearestFilter, NormalBlending, Object3D, PlaneGeometry } from "three";
|
|
9
9
|
//#region src/2d/physics/collider-validate.ts
|
|
@@ -214,6 +214,28 @@ var CharacterBody2D = class extends PhysicsBody2D {
|
|
|
214
214
|
if (!this._physics) throw new IncantoError("TREE_VIOLATION", this.collider.shape === void 0 ? `CharacterBody2D '${this.name}' has no collider — set a collider prop (physics skips collider-less bodies).` : `CharacterBody2D '${this.name}' has no physics world — await enablePhysics2D(engine) first.`);
|
|
215
215
|
this._physics.moveAndSlide(this);
|
|
216
216
|
}
|
|
217
|
+
/** @internal Set by the physics step from the KCC's resolved collisions. */
|
|
218
|
+
_onWall = 0;
|
|
219
|
+
/** @internal */
|
|
220
|
+
_onCeiling = false;
|
|
221
|
+
/**
|
|
222
|
+
* Touching a wall, and which side (-1 left, +1 right, 0 neither).
|
|
223
|
+
*
|
|
224
|
+
* Wall jump and wall slide are unbuildable without it — not awkward to build,
|
|
225
|
+
* impossible: `isOnFloor()` was the only surface a character could report, so
|
|
226
|
+
* even a hand-written behavior had nothing to ask.
|
|
227
|
+
*/
|
|
228
|
+
isOnWall() {
|
|
229
|
+
return this._onWall !== 0;
|
|
230
|
+
}
|
|
231
|
+
/** -1 the wall is to the left, +1 to the right, 0 no wall. */
|
|
232
|
+
wallSide() {
|
|
233
|
+
return this._onWall;
|
|
234
|
+
}
|
|
235
|
+
/** Head hit something — cut the jump short, the way every platformer does. */
|
|
236
|
+
isOnCeiling() {
|
|
237
|
+
return this._onCeiling;
|
|
238
|
+
}
|
|
217
239
|
isOnFloor() {
|
|
218
240
|
return this._grounded;
|
|
219
241
|
}
|
|
@@ -521,6 +543,18 @@ function clampCentered(v, lo, hi) {
|
|
|
521
543
|
* - `platformer`: x movement + gravity (from the scene `physics.gravity[1]`,
|
|
522
544
|
* default 980) + jump (`jumpHeight` px → impulse √(2·g·h))
|
|
523
545
|
* - `topDown`: full-axis movement, no gravity
|
|
546
|
+
*
|
|
547
|
+
* ## Why the extra platformer props exist
|
|
548
|
+
*
|
|
549
|
+
* A jump that only works while `isOnFloor()` is true feels BROKEN, and players
|
|
550
|
+
* do not report it as "the coyote time is missing" — they report the game as
|
|
551
|
+
* unresponsive. The whole schema used to be five props, so a JSON-only game got
|
|
552
|
+
* a character that felt wrong and could not drive `AnimatedSprite2D.play('run')`
|
|
553
|
+
* either. `examples/platformer-2d` hand-rolls all of this in a 541-line
|
|
554
|
+
* behavior; these are those constants, as props.
|
|
555
|
+
*
|
|
556
|
+
* Every one defaults to OFF (0 / 1 / false), so an existing scene behaves
|
|
557
|
+
* exactly as before until it asks for something.
|
|
524
558
|
*/
|
|
525
559
|
var CharacterController2D = class extends Node {
|
|
526
560
|
static typeName = "CharacterController2D";
|
|
@@ -532,14 +566,48 @@ var CharacterController2D = class extends Node {
|
|
|
532
566
|
maxSpeed: { default: 220 },
|
|
533
567
|
jumpHeight: { default: 64 },
|
|
534
568
|
moveAction: { default: "move" },
|
|
535
|
-
jumpAction: { default: "jump" }
|
|
569
|
+
jumpAction: { default: "jump" },
|
|
570
|
+
/** Jump this long AFTER walking off a ledge. The single biggest one. */
|
|
571
|
+
coyoteSeconds: { default: 0 },
|
|
572
|
+
/** Press jump this long BEFORE landing and still get it. */
|
|
573
|
+
jumpBufferSeconds: { default: 0 },
|
|
574
|
+
/** Releasing jump early cuts the rise to this fraction (1 = fixed height). */
|
|
575
|
+
jumpCutMultiplier: { default: 1 },
|
|
576
|
+
/** 2 = double jump. Extra jumps work in mid-air. */
|
|
577
|
+
maxJumps: { default: 1 },
|
|
578
|
+
/** 0 = no dash. Speed while dashing, in px/s. */
|
|
579
|
+
dashSpeed: { default: 0 },
|
|
580
|
+
dashSeconds: { default: .15 },
|
|
581
|
+
dashAction: { default: "dash" },
|
|
582
|
+
/** 0 = no wall slide. Terminal fall speed while against a wall (px/s). */
|
|
583
|
+
wallSlideSpeed: { default: 0 },
|
|
584
|
+
/** 0 = no wall jump. `[away, up]` impulse in px/s. */
|
|
585
|
+
wallJumpImpulse: { default: [0, 0] }
|
|
536
586
|
};
|
|
587
|
+
static signals = ["movementStateChanged"];
|
|
537
588
|
mode = "platformer";
|
|
538
589
|
maxSpeed = 220;
|
|
539
590
|
/** Pixels (platformer mode). */
|
|
540
591
|
jumpHeight = 64;
|
|
541
592
|
moveAction = "move";
|
|
542
593
|
jumpAction = "jump";
|
|
594
|
+
coyoteSeconds = 0;
|
|
595
|
+
jumpBufferSeconds = 0;
|
|
596
|
+
jumpCutMultiplier = 1;
|
|
597
|
+
maxJumps = 1;
|
|
598
|
+
dashSpeed = 0;
|
|
599
|
+
dashSeconds = .15;
|
|
600
|
+
dashAction = "dash";
|
|
601
|
+
wallSlideSpeed = 0;
|
|
602
|
+
wallJumpImpulse = [0, 0];
|
|
603
|
+
/** What the character is doing — drive `AnimatedSprite2D.play(state)` off it. */
|
|
604
|
+
state = "idle";
|
|
605
|
+
coyoteLeft = 0;
|
|
606
|
+
bufferLeft = 0;
|
|
607
|
+
jumpsUsed = 0;
|
|
608
|
+
dashLeft = 0;
|
|
609
|
+
dashDir = 1;
|
|
610
|
+
rising = false;
|
|
543
611
|
onReady() {
|
|
544
612
|
if (!(this.parent instanceof CharacterBody2D)) throw new IncantoError("TREE_VIOLATION", `CharacterController2D '${this.name}' must be a child of a CharacterBody2D (parent is '${this.parent?.name ?? "none"}').`);
|
|
545
613
|
if (this.mode !== "platformer" && this.mode !== "topDown") throw new IncantoError("PROP_TYPE_MISMATCH", `CharacterController2D.mode must be 'platformer' or 'topDown', got '${this.mode}'.`);
|
|
@@ -557,12 +625,81 @@ var CharacterController2D = class extends Node {
|
|
|
557
625
|
return;
|
|
558
626
|
}
|
|
559
627
|
const gravityY = (engine.scene.physics?.gravity)?.[1] ?? 980;
|
|
628
|
+
const grounded = body.isOnFloor();
|
|
629
|
+
const jumpImpulse = -Math.sqrt(2 * gravityY * this.jumpHeight);
|
|
630
|
+
if (this.dashLeft > 0) {
|
|
631
|
+
this.dashLeft -= dt;
|
|
632
|
+
body.velocity[0] = this.dashDir * this.dashSpeed;
|
|
633
|
+
body.velocity[1] = 0;
|
|
634
|
+
body.moveAndSlide();
|
|
635
|
+
this.setState("dash");
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
if (this.dashSpeed > 0 && input.justPressed(this.dashAction)) {
|
|
639
|
+
this.dashLeft = this.dashSeconds;
|
|
640
|
+
this.dashDir = dir.x !== 0 ? Math.sign(dir.x) : this.dashDir;
|
|
641
|
+
body.velocity[0] = this.dashDir * this.dashSpeed;
|
|
642
|
+
body.velocity[1] = 0;
|
|
643
|
+
body.moveAndSlide();
|
|
644
|
+
this.setState("dash");
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
560
647
|
body.velocity[0] = dir.x * this.maxSpeed;
|
|
561
|
-
if (
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
} else
|
|
648
|
+
if (grounded) {
|
|
649
|
+
this.coyoteLeft = this.coyoteSeconds;
|
|
650
|
+
this.jumpsUsed = 0;
|
|
651
|
+
} else {
|
|
652
|
+
this.coyoteLeft = Math.max(0, this.coyoteLeft - dt);
|
|
653
|
+
if (this.coyoteLeft <= 0 && this.jumpsUsed === 0) this.jumpsUsed = 1;
|
|
654
|
+
}
|
|
655
|
+
if (input.justPressed(this.jumpAction)) this.bufferLeft = Math.max(this.jumpBufferSeconds, 0);
|
|
656
|
+
else this.bufferLeft = Math.max(0, this.bufferLeft - dt);
|
|
657
|
+
const wantsJump = this.bufferLeft > 0 || input.justPressed(this.jumpAction);
|
|
658
|
+
const onWall = this.wallSlideSpeed > 0 || this.wallJumpImpulse.some((v) => v !== 0) ? body.isOnWall() : false;
|
|
659
|
+
if (wantsJump && onWall && !grounded && this.wallJumpImpulse.some((v) => v !== 0)) {
|
|
660
|
+
const away = -body.wallSide();
|
|
661
|
+
body.velocity[0] = away * (this.wallJumpImpulse[0] ?? 0);
|
|
662
|
+
body.velocity[1] = -(this.wallJumpImpulse[1] ?? 0);
|
|
663
|
+
this.bufferLeft = 0;
|
|
664
|
+
this.rising = true;
|
|
665
|
+
this.jumpsUsed = 1;
|
|
666
|
+
} else if (wantsJump && (grounded || this.coyoteLeft > 0 || this.jumpsUsed < this.maxJumps)) {
|
|
667
|
+
body.velocity[1] = jumpImpulse;
|
|
668
|
+
this.bufferLeft = 0;
|
|
669
|
+
this.coyoteLeft = 0;
|
|
670
|
+
this.rising = true;
|
|
671
|
+
this.jumpsUsed = grounded ? 1 : this.jumpsUsed + 1;
|
|
672
|
+
} else if (grounded) {
|
|
673
|
+
body.velocity[1] = 20;
|
|
674
|
+
this.rising = false;
|
|
675
|
+
} else {
|
|
676
|
+
body.velocity[1] = (body.velocity[1] ?? 0) + gravityY * dt;
|
|
677
|
+
if (this.rising && this.jumpCutMultiplier < 1 && !input.isPressed(this.jumpAction)) {
|
|
678
|
+
body.velocity[1] = (body.velocity[1] ?? 0) * this.jumpCutMultiplier;
|
|
679
|
+
this.rising = false;
|
|
680
|
+
}
|
|
681
|
+
if ((body.velocity[1] ?? 0) >= 0) this.rising = false;
|
|
682
|
+
if (this.wallSlideSpeed > 0 && onWall && (body.velocity[1] ?? 0) > this.wallSlideSpeed) body.velocity[1] = this.wallSlideSpeed;
|
|
683
|
+
}
|
|
684
|
+
if (body.isOnCeiling() && (body.velocity[1] ?? 0) < 0) {
|
|
685
|
+
body.velocity[1] = 0;
|
|
686
|
+
this.rising = false;
|
|
687
|
+
}
|
|
565
688
|
body.moveAndSlide();
|
|
689
|
+
const vy = body.velocity[1] ?? 0;
|
|
690
|
+
if (this.wallSlideSpeed > 0 && !body.isOnFloor() && body.isOnWall() && vy > 0) this.setState("wallSlide");
|
|
691
|
+
else if (body.isOnFloor()) this.setState(Math.abs(dir.x) > .01 ? "run" : "idle");
|
|
692
|
+
else this.setState(vy < 0 ? "jump" : "fall");
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* Emits `movementStateChanged(state)` on a change — the 3D sibling has had
|
|
696
|
+
* this since it shipped, and it is what drives `AnimatedSprite2D.play(...)`
|
|
697
|
+
* from scene JSON instead of a behavior polling velocities.
|
|
698
|
+
*/
|
|
699
|
+
setState(next) {
|
|
700
|
+
if (next === this.state) return;
|
|
701
|
+
this.state = next;
|
|
702
|
+
this.emit("movementStateChanged", next);
|
|
566
703
|
}
|
|
567
704
|
};
|
|
568
705
|
//#endregion
|