incanto 0.1.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.
Files changed (138) hide show
  1. package/LICENSE +30 -0
  2. package/README.md +36 -0
  3. package/THIRD-PARTY-NOTICES.md +88 -0
  4. package/assets/audio/attacked.mp3 +0 -0
  5. package/assets/audio/explosion.mp3 +0 -0
  6. package/assets/audio/gold_loot.mp3 +0 -0
  7. package/assets/audio/heal.mp3 +0 -0
  8. package/assets/audio/hit_metal_bang.mp3 +0 -0
  9. package/assets/audio/ice_spear.mp3 +0 -0
  10. package/assets/audio/monster_died.mp3 +0 -0
  11. package/assets/audio/slash.mp3 +0 -0
  12. package/assets/audio/smite.mp3 +0 -0
  13. package/assets/audio/spells_cast.mp3 +0 -0
  14. package/assets/audio/ui_click.wav +0 -0
  15. package/assets/audio/walk.mp3 +0 -0
  16. package/assets/catalog.json +390 -0
  17. package/assets/characters/2dbasic.json +41 -0
  18. package/assets/characters/2dbasic.png +0 -0
  19. package/assets/characters/ghost.json +46 -0
  20. package/assets/characters/ghost.png +0 -0
  21. package/assets/characters/goblin.json +40 -0
  22. package/assets/characters/goblin.png +0 -0
  23. package/assets/characters/medieval-knight.json +41 -0
  24. package/assets/characters/medieval-knight.png +0 -0
  25. package/assets/effects/swoosh.png +0 -0
  26. package/assets/items/box.png +0 -0
  27. package/assets/items/buff_potion.png +0 -0
  28. package/assets/items/coin.png +0 -0
  29. package/assets/items/gem.png +0 -0
  30. package/assets/items/gold.png +0 -0
  31. package/assets/items/hp_potion.png +0 -0
  32. package/assets/items/locked_item_box.png +0 -0
  33. package/assets/items/map.png +0 -0
  34. package/assets/items/resurrection_potion.png +0 -0
  35. package/assets/items/super_box.png +0 -0
  36. package/assets/items/trap.png +0 -0
  37. package/assets/tiles/floor00.jpg +0 -0
  38. package/assets/tiles/minecraft-tiles.png +0 -0
  39. package/assets/tiles/wall00.jpg +0 -0
  40. package/assets/vegetation/ash_color.png +0 -0
  41. package/assets/vegetation/aspen_color.png +0 -0
  42. package/assets/vegetation/bark/birch_color_1k.jpg +0 -0
  43. package/assets/vegetation/bark/birch_normal_1k.jpg +0 -0
  44. package/assets/vegetation/bark/birch_roughness_1k.jpg +0 -0
  45. package/assets/vegetation/bark/oak_color_1k.jpg +0 -0
  46. package/assets/vegetation/bark/oak_normal_1k.jpg +0 -0
  47. package/assets/vegetation/bark/oak_roughness_1k.jpg +0 -0
  48. package/assets/vegetation/bark/pine_color_1k.jpg +0 -0
  49. package/assets/vegetation/bark/pine_normal_1k.jpg +0 -0
  50. package/assets/vegetation/bark/pine_roughness_1k.jpg +0 -0
  51. package/assets/vegetation/ground/dirt_color.jpg +0 -0
  52. package/assets/vegetation/ground/dirt_normal.jpg +0 -0
  53. package/assets/vegetation/ground/grass.jpg +0 -0
  54. package/assets/vegetation/oak_color.png +0 -0
  55. package/assets/vegetation/pine_color.png +0 -0
  56. package/bin/incanto-assets.mjs +107 -0
  57. package/bin/incanto-check.mjs +107 -0
  58. package/bin/incanto-editor.mjs +343 -0
  59. package/bin/incanto-env.mjs +144 -0
  60. package/bin/incanto-model.mjs +296 -0
  61. package/bin/incanto-play.mjs +219 -0
  62. package/bin/incanto-skills.mjs +71 -0
  63. package/dist/2d.d.ts +642 -0
  64. package/dist/2d.js +44 -0
  65. package/dist/3d.d.ts +1860 -0
  66. package/dist/3d.js +5 -0
  67. package/dist/agent8-DzU2fFyH.js +129 -0
  68. package/dist/audio-player-DqUR3XFs.d.ts +110 -0
  69. package/dist/behavior-BAQq7HGM.d.ts +851 -0
  70. package/dist/create-game-BdjpTHrW.js +1725 -0
  71. package/dist/create-game-CZHROKcT.js +527 -0
  72. package/dist/debug-draw-CZmOYjL2.js +13 -0
  73. package/dist/debug.d.ts +66 -0
  74. package/dist/debug.js +658 -0
  75. package/dist/duplicate-DP2WPYom.js +22 -0
  76. package/dist/env.d.ts +430 -0
  77. package/dist/env.js +3152 -0
  78. package/dist/errors-BMFaY68Q.d.ts +33 -0
  79. package/dist/errors-BpWbnbb_.js +13 -0
  80. package/dist/gameplay-Ccruc3Wd.js +1501 -0
  81. package/dist/gameplay.d.ts +543 -0
  82. package/dist/gameplay.js +2 -0
  83. package/dist/heightmap-CroQPEER.js +185 -0
  84. package/dist/index.d.ts +305 -0
  85. package/dist/index.js +62 -0
  86. package/dist/json-BLk7H2Qa.js +30 -0
  87. package/dist/loader-CGs_G-r0.js +919 -0
  88. package/dist/loader-Mo0KghCv.d.ts +41 -0
  89. package/dist/net.d.ts +427 -0
  90. package/dist/net.js +772 -0
  91. package/dist/noise-CGUMx44x.js +82 -0
  92. package/dist/particle-sim-CbN4YUuH.d.ts +63 -0
  93. package/dist/particle-sim-DYuSUxvK.js +1319 -0
  94. package/dist/physics-2d-KuMWPTf6.js +288 -0
  95. package/dist/physics-3d-Dl67vOLT.js +434 -0
  96. package/dist/react.d.ts +65 -0
  97. package/dist/react.js +209 -0
  98. package/dist/register-BuUV1_KB.js +561 -0
  99. package/dist/register-CNlYAS1_.js +10634 -0
  100. package/dist/register-DPEV9_9t.js +851 -0
  101. package/dist/register-Dasmnurl.js +374 -0
  102. package/dist/registry-BVJ2HbCn.js +132 -0
  103. package/dist/rng-DP-SR7eg.js +38 -0
  104. package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
  105. package/dist/schema-CcoWb32N.d.ts +104 -0
  106. package/dist/test.d.ts +158 -0
  107. package/dist/test.js +275 -0
  108. package/dist/touch-031PxtCR.js +208 -0
  109. package/dist/vite.d.ts +26 -0
  110. package/dist/vite.js +57 -0
  111. package/editor/assets/GameServer-C56iOUgF.js +1 -0
  112. package/editor/assets/agent8-Bp7QFI7v.js +1 -0
  113. package/editor/assets/index-DF3tMeKJ.css +1 -0
  114. package/editor/assets/index-Dl2pjA8e.js +7365 -0
  115. package/editor/assets/rapier-CEuLKeCu.js +1 -0
  116. package/editor/assets/rapier-DE6a0vmv.js +1 -0
  117. package/editor/index.html +169 -0
  118. package/package.json +97 -0
  119. package/schemas/scene.schema.json +4254 -0
  120. package/skills/README.md +9 -0
  121. package/skills/incanto-3d-character.md +229 -0
  122. package/skills/incanto-3d-models.md +151 -0
  123. package/skills/incanto-assets.md +118 -0
  124. package/skills/incanto-audio.md +309 -0
  125. package/skills/incanto-behaviors-and-scripts.md +169 -0
  126. package/skills/incanto-building-2d-games.md +242 -0
  127. package/skills/incanto-building-3d-games.md +245 -0
  128. package/skills/incanto-editor.md +163 -0
  129. package/skills/incanto-environment.md +743 -0
  130. package/skills/incanto-gameplay-behaviors.md +707 -0
  131. package/skills/incanto-multiplayer.md +264 -0
  132. package/skills/incanto-node-reference.md +797 -0
  133. package/skills/incanto-physics-and-input.md +164 -0
  134. package/skills/incanto-scene-json-authoring.md +325 -0
  135. package/skills/incanto-verifying-your-game.md +191 -0
  136. package/skills/incanto-web-integration.md +96 -0
  137. package/templates/agent8-server.js +84 -0
  138. package/templates/agent8-server.ts +138 -0
@@ -0,0 +1,288 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
+ import { t as IncantoError } from "./errors-BpWbnbb_.js";
3
+ import { d as CharacterBody2D, f as PhysicsBody2D, g as validateCollider2D, h as Node2D, p as RigidBody2D, u as Area2D } from "./register-DPEV9_9t.js";
4
+ import { n as registerDebugSource } from "./debug-draw-CZmOYjL2.js";
5
+ //#region src/2d/physics/physics-2d.ts
6
+ var physics_2d_exports = /* @__PURE__ */ __exportAll({
7
+ Physics2D: () => Physics2D,
8
+ enablePhysics2D: () => enablePhysics2D
9
+ });
10
+ /** Internal unit scale: Rapier's solver is tuned for meters; we speak pixels. */
11
+ const SCALE = 100;
12
+ const DEG = Math.PI / 180;
13
+ /**
14
+ * Enable 2D physics for an engine. Dynamically imports Rapier (compat build,
15
+ * wasm inlined) so games without physics never pay its bundle cost.
16
+ */
17
+ async function enablePhysics2D(engine, opts) {
18
+ const R = await import("@dimforge/rapier2d-compat");
19
+ await R.init();
20
+ return new Physics2D(R, engine, opts);
21
+ }
22
+ /**
23
+ * Per-engine 2D physics world (y-down pixel space, consistent with Node2D).
24
+ * Each fixedUpdate: sync tree → step world → write back → drain trigger events.
25
+ */
26
+ var Physics2D = class {
27
+ R;
28
+ engine;
29
+ /** Render collider outlines in the GAME view (renderers pick this up). */
30
+ debugDraw = false;
31
+ dimension = "2d";
32
+ unregisterDebug;
33
+ warnedNoCollider = /* @__PURE__ */ new WeakSet();
34
+ entries = /* @__PURE__ */ new Map();
35
+ byColliderHandle = /* @__PURE__ */ new Map();
36
+ world;
37
+ events;
38
+ kcc;
39
+ disconnect;
40
+ lastDt = 1 / 60;
41
+ optsGravity;
42
+ lastScene = null;
43
+ constructor(R, engine, opts) {
44
+ this.R = R;
45
+ this.engine = engine;
46
+ this.optsGravity = opts?.gravity;
47
+ this.lastScene = engine.scene;
48
+ const declared = engine.scene?.physics?.gravity;
49
+ const g = opts?.gravity ?? declared ?? [0, 980];
50
+ this.world = new R.World({
51
+ x: (g[0] ?? 0) / SCALE,
52
+ y: (g[1] ?? 0) / SCALE
53
+ });
54
+ this.kcc = this.world.createCharacterController(.01);
55
+ this.kcc.setUp({
56
+ x: 0,
57
+ y: -1
58
+ });
59
+ this.events = new R.EventQueue(true);
60
+ this.unregisterDebug = registerDebugSource(this);
61
+ this.disconnect = engine.fixedUpdated.connect((dt) => this.step(dt));
62
+ this.syncBodies();
63
+ }
64
+ /** @internal Driven by engine.fixedUpdated. */
65
+ step(dt) {
66
+ this.lastDt = dt;
67
+ if (this.engine.scene !== this.lastScene) {
68
+ this.lastScene = this.engine.scene;
69
+ if (!this.optsGravity) {
70
+ const g = this.engine.scene?.physics?.gravity ?? [0, 980];
71
+ this.world.gravity = {
72
+ x: (g[0] ?? 0) / SCALE,
73
+ y: (g[1] ?? 0) / SCALE
74
+ };
75
+ }
76
+ }
77
+ this.syncBodies();
78
+ this.world.timestep = dt;
79
+ this.world.step(this.events);
80
+ for (const [node, e] of this.entries) {
81
+ const t = e.body.translation();
82
+ if (!e.body.isFixed()) {
83
+ const [ox, oy] = parentWorldOffset2D(node);
84
+ node.position = [t.x * SCALE - ox, t.y * SCALE - oy];
85
+ }
86
+ if (node instanceof RigidBody2D) {
87
+ if (!node.fixedRotation) node.rotation = e.body.rotation() / DEG;
88
+ const lv = e.body.linvel();
89
+ node.linearVelocity = [lv.x * SCALE, lv.y * SCALE];
90
+ e.lastVX = node.linearVelocity[0] ?? 0;
91
+ e.lastVY = node.linearVelocity[1] ?? 0;
92
+ }
93
+ const [wx, wy] = worldPosition2D(node);
94
+ e.lastX = wx;
95
+ e.lastY = wy;
96
+ }
97
+ this.events.drainCollisionEvents((h1, h2, started) => {
98
+ const a = this.byColliderHandle.get(h1);
99
+ const b = this.byColliderHandle.get(h2);
100
+ if (!a || !b) return;
101
+ const sig = started ? "triggerEnter" : "triggerExit";
102
+ a.emit(sig, b);
103
+ b.emit(sig, a);
104
+ });
105
+ }
106
+ /** @internal Called by CharacterBody2D.moveAndSlide (during tree fixedUpdate). */
107
+ moveAndSlide(node) {
108
+ const e = this.ensureEntry(node);
109
+ const vy = node.velocity[1] ?? 0;
110
+ if (node.snapToGround && vy >= 0) this.kcc.enableSnapToGround(.05);
111
+ else this.kcc.disableSnapToGround();
112
+ this.kcc.setMaxSlopeClimbAngle(node.slopeLimitDeg * DEG);
113
+ const desired = {
114
+ x: (node.velocity[0] ?? 0) * this.lastDt / SCALE,
115
+ y: vy * this.lastDt / SCALE
116
+ };
117
+ this.kcc.computeColliderMovement(e.collider, desired, this.R.QueryFilterFlags.EXCLUDE_SENSORS);
118
+ const corrected = this.kcc.computedMovement();
119
+ const t = e.body.translation();
120
+ e.body.setNextKinematicTranslation({
121
+ x: t.x + corrected.x,
122
+ y: t.y + corrected.y
123
+ });
124
+ node._grounded = this.kcc.computedGrounded();
125
+ }
126
+ /** Rapier debug segments, scaled back to pixels. Null while debugDraw is off. */
127
+ debugLines() {
128
+ if (!this.debugDraw) return null;
129
+ const raw = this.world.debugRender().vertices;
130
+ const px = new Float32Array(raw.length);
131
+ for (let i = 0; i < raw.length; i++) px[i] = raw[i] * SCALE;
132
+ return px;
133
+ }
134
+ dispose() {
135
+ this.disconnect();
136
+ this.unregisterDebug();
137
+ this.world.free();
138
+ }
139
+ syncBodies() {
140
+ const scene = this.engine.scene;
141
+ if (!scene) return;
142
+ const seen = /* @__PURE__ */ new Set();
143
+ collectBodies(scene.root, seen);
144
+ for (const node of seen) {
145
+ if (node.collider.shape === void 0) {
146
+ const stale = this.entries.get(node);
147
+ if (stale) {
148
+ this.byColliderHandle.delete(stale.collider.handle);
149
+ this.world.removeRigidBody(stale.body);
150
+ this.entries.delete(node);
151
+ node._physics = null;
152
+ }
153
+ if (!this.warnedNoCollider.has(node)) {
154
+ this.warnedNoCollider.add(node);
155
+ console.warn(`[incanto] '${node.name}' has no collider — physics skips it.`);
156
+ }
157
+ continue;
158
+ }
159
+ const existing = this.entries.get(node);
160
+ if (existing && existing.colliderKey !== JSON.stringify(node.collider)) {
161
+ this.byColliderHandle.delete(existing.collider.handle);
162
+ this.world.removeRigidBody(existing.body);
163
+ this.entries.delete(node);
164
+ node._physics = null;
165
+ }
166
+ this.ensureEntry(node);
167
+ }
168
+ for (const [node, e] of this.entries) if (!seen.has(node)) {
169
+ this.byColliderHandle.delete(e.collider.handle);
170
+ this.world.removeRigidBody(e.body);
171
+ this.entries.delete(node);
172
+ node._physics = null;
173
+ }
174
+ }
175
+ ensureEntry(node) {
176
+ let e = this.entries.get(node);
177
+ const R = this.R;
178
+ if (!e) {
179
+ const [wx, wy] = worldPosition2D(node);
180
+ const x = wx / SCALE;
181
+ const y = wy / SCALE;
182
+ let desc;
183
+ if (node instanceof RigidBody2D) desc = R.RigidBodyDesc.dynamic();
184
+ else if (node instanceof CharacterBody2D || node instanceof Area2D) desc = R.RigidBodyDesc.kinematicPositionBased();
185
+ else desc = R.RigidBodyDesc.fixed();
186
+ desc.setTranslation(x, y).setRotation(node.rotation * DEG);
187
+ if (node instanceof RigidBody2D) {
188
+ desc.setGravityScale(node.gravityScale);
189
+ desc.setLinvel((node.linearVelocity[0] ?? 0) / SCALE, (node.linearVelocity[1] ?? 0) / SCALE);
190
+ if (node.fixedRotation) desc.lockRotations();
191
+ }
192
+ const body = this.world.createRigidBody(desc);
193
+ const colDesc = parseCollider2D(R, node.collider, node.name);
194
+ colDesc.setActiveEvents(R.ActiveEvents.COLLISION_EVENTS);
195
+ colDesc.setActiveCollisionTypes(R.ActiveCollisionTypes.ALL);
196
+ if (node instanceof Area2D) colDesc.setSensor(true);
197
+ if (node instanceof RigidBody2D) colDesc.setMass(node.mass).setFriction(node.friction).setRestitution(node.restitution);
198
+ const collider = this.world.createCollider(colDesc, body);
199
+ e = {
200
+ body,
201
+ collider,
202
+ colliderKey: JSON.stringify(node.collider),
203
+ lastX: wx,
204
+ lastY: wy,
205
+ lastVX: 0,
206
+ lastVY: 0
207
+ };
208
+ this.entries.set(node, e);
209
+ this.byColliderHandle.set(collider.handle, node);
210
+ node._physics = this;
211
+ return e;
212
+ }
213
+ const [px, py] = worldPosition2D(node);
214
+ if (px !== e.lastX || py !== e.lastY) {
215
+ e.body.setTranslation({
216
+ x: px / SCALE,
217
+ y: py / SCALE
218
+ }, true);
219
+ e.lastX = px;
220
+ e.lastY = py;
221
+ }
222
+ if (node instanceof RigidBody2D) {
223
+ const vx = node.linearVelocity[0] ?? 0;
224
+ const vy = node.linearVelocity[1] ?? 0;
225
+ if (vx !== e.lastVX || vy !== e.lastVY) {
226
+ e.body.setLinvel({
227
+ x: vx / SCALE,
228
+ y: vy / SCALE
229
+ }, true);
230
+ e.lastVX = vx;
231
+ e.lastVY = vy;
232
+ }
233
+ }
234
+ return e;
235
+ }
236
+ };
237
+ function collectBodies(node, out) {
238
+ if (node instanceof PhysicsBody2D) out.add(node);
239
+ for (const c of node.children) collectBodies(c, out);
240
+ }
241
+ /**
242
+ * Composed world position (translation only — ancestor rotation/scale are NOT
243
+ * supported for physics bodies; keep body ancestors untransformed or offset-only).
244
+ */
245
+ function worldPosition2D(node) {
246
+ let x = 0;
247
+ let y = 0;
248
+ for (let n = node; n; n = n.parent) if (n instanceof Node2D) {
249
+ x += n.position[0] ?? 0;
250
+ y += n.position[1] ?? 0;
251
+ }
252
+ return [x, y];
253
+ }
254
+ function parentWorldOffset2D(node) {
255
+ let x = 0;
256
+ let y = 0;
257
+ for (let n = node.parent; n; n = n.parent) if (n instanceof Node2D) {
258
+ x += n.position[0] ?? 0;
259
+ y += n.position[1] ?? 0;
260
+ }
261
+ return [x, y];
262
+ }
263
+ function parseCollider2D(R, collider, nodeName) {
264
+ validateCollider2D(collider, nodeName);
265
+ const desc = buildColliderDesc(R, collider, nodeName);
266
+ const offset = collider.offset;
267
+ if (Array.isArray(offset)) desc.setTranslation((offset[0] ?? 0) / SCALE, (offset[1] ?? 0) / SCALE);
268
+ return desc;
269
+ }
270
+ function buildColliderDesc(R, collider, nodeName) {
271
+ const shape = collider.shape;
272
+ if (shape === "rect") {
273
+ const size = collider.size;
274
+ if (!Array.isArray(size) || size.length !== 2 || size.some((v) => typeof v !== "number")) throw new IncantoError("BAD_FORMAT", `Collider on '${nodeName}': rect needs "size": [width, height].`);
275
+ return R.ColliderDesc.cuboid(size[0] / 2 / SCALE, size[1] / 2 / SCALE);
276
+ }
277
+ if (shape === "circle") {
278
+ if (typeof collider.radius !== "number") throw new IncantoError("BAD_FORMAT", `Collider on '${nodeName}': circle needs "radius".`);
279
+ return R.ColliderDesc.ball(collider.radius / SCALE);
280
+ }
281
+ if (shape === "capsule") {
282
+ if (typeof collider.radius !== "number" || typeof collider.height !== "number") throw new IncantoError("BAD_FORMAT", `Collider on '${nodeName}': capsule needs "radius" and "height".`);
283
+ return R.ColliderDesc.capsule(collider.height / 2 / SCALE, collider.radius / SCALE);
284
+ }
285
+ throw new IncantoError("BAD_FORMAT", `Collider on '${nodeName}': "shape" must be 'rect', 'circle', or 'capsule', got ${JSON.stringify(shape)}.`);
286
+ }
287
+ //#endregion
288
+ export { enablePhysics2D as n, physics_2d_exports as r, Physics2D as t };