incanto 0.76.0 → 0.78.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/index.js +1 -1
- package/dist/{src-D823V07k.js → src-DzPtpk1t.js} +1 -1
- package/dist/vite.d.ts +47 -3
- package/dist/vite.js +49 -17
- package/package.json +1 -1
- package/skills/incanto-building-2d-games.md +6 -0
- package/skills/incanto-building-3d-games.md +6 -0
- package/skills/incanto-editor.md +46 -2
- package/skills/incanto-multiplayer.md +1 -1
- package/skills/incanto-save-slots.md +1 -1
- package/skills/incanto-scene-json-authoring.md +1 -1
- package/skills/incanto-verifying-your-game.md +2 -2
- package/skills/incanto-web-integration.md +40 -2
- package/skills/incanto-your-first-game.md +6 -1
- package/templates-app/beacon-isle-3d/PROJECT/Structure.md +2 -1
- package/templates-app/beacon-isle-3d/index.html +5 -2
- package/templates-app/beacon-isle-3d/package.json +6 -1
- package/templates-app/beacon-isle-3d/src/App.tsx +77 -0
- package/templates-app/beacon-isle-3d/src/main.tsx +9 -0
- package/templates-app/beacon-isle-3d/tsconfig.json +2 -1
- package/templates-app/beacon-isle-3d/vite.config.ts +4 -1
- package/templates-app/molehill-2d/PROJECT/Structure.md +2 -1
- package/templates-app/molehill-2d/index.html +5 -2
- package/templates-app/molehill-2d/package.json +6 -1
- package/templates-app/molehill-2d/src/App.tsx +58 -0
- package/templates-app/molehill-2d/src/main.tsx +9 -0
- package/templates-app/molehill-2d/tsconfig.json +2 -1
- package/templates-app/molehill-2d/vite.config.ts +4 -1
- package/templates-app/platformer-2d/PROJECT/Context.md +1 -1
- package/templates-app/platformer-2d/PROJECT/Requirements.md +2 -2
- package/templates-app/platformer-2d/PROJECT/Status.md +1 -1
- package/templates-app/platformer-2d/PROJECT/Structure.md +2 -2
- package/templates-app/platformer-2d/docs/project-2d-rules.md +1 -1
- package/templates-app/platformer-2d/index.html +5 -2
- package/templates-app/platformer-2d/package.json +6 -1
- package/templates-app/platformer-2d/src/App.tsx +115 -0
- package/templates-app/platformer-2d/src/main.tsx +9 -0
- package/templates-app/platformer-2d/tsconfig.json +2 -1
- package/templates-app/platformer-2d/vite.config.ts +4 -1
- package/templates-app/star-survivor/PROJECT/Context.md +1 -1
- package/templates-app/star-survivor/PROJECT/Requirements.md +1 -1
- package/templates-app/star-survivor/PROJECT/Status.md +1 -1
- package/templates-app/star-survivor/PROJECT/Structure.md +2 -2
- package/templates-app/star-survivor/docs/project-2d-rules.md +1 -1
- package/templates-app/star-survivor/index.html +5 -2
- package/templates-app/star-survivor/package.json +6 -1
- package/templates-app/star-survivor/src/App.tsx +94 -0
- package/templates-app/star-survivor/src/main.tsx +9 -0
- package/templates-app/star-survivor/tsconfig.json +2 -1
- package/templates-app/star-survivor/vite.config.ts +4 -1
- package/templates-app/tps-3d/PROJECT/Status.md +1 -1
- package/templates-app/tps-3d/PROJECT/Structure.md +2 -2
- package/templates-app/tps-3d/index.html +5 -2
- package/templates-app/tps-3d/package.json +6 -1
- package/templates-app/tps-3d/src/App.tsx +124 -0
- package/templates-app/tps-3d/src/main.tsx +9 -0
- package/templates-app/tps-3d/tsconfig.json +2 -1
- package/templates-app/tps-3d/vite.config.ts +4 -1
- package/templates-app/village-quest-3d/PROJECT/Structure.md +3 -2
- package/templates-app/village-quest-3d/index.html +5 -2
- package/templates-app/village-quest-3d/package.json +6 -1
- package/templates-app/village-quest-3d/src/App.tsx +79 -0
- package/templates-app/village-quest-3d/src/main.tsx +9 -0
- package/templates-app/village-quest-3d/tsconfig.json +2 -1
- package/templates-app/village-quest-3d/vite.config.ts +4 -1
- package/templates-app/beacon-isle-3d/src/main.ts +0 -60
- package/templates-app/molehill-2d/src/main.ts +0 -41
- package/templates-app/platformer-2d/src/main.ts +0 -97
- package/templates-app/star-survivor/src/main.ts +0 -77
- package/templates-app/tps-3d/src/main.ts +0 -107
- package/templates-app/village-quest-3d/src/main.ts +0 -62
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hollow Horde — a top-down SURVIVORS-LIKE (Vampire Survivors genre) on Incanto.
|
|
3
|
-
* Move with WASD / arrows; your knight AUTO-ATTACKS the nearest enemy. Goblins and
|
|
4
|
-
* faster ghosts pour in from every side and grow tougher over time. Cut them down,
|
|
5
|
-
* vacuum up the XP shards they drop, and on each LEVEL-UP pick one of three
|
|
6
|
-
* upgrades. Survive 90 seconds to win — let the horde drain your HP and you fall.
|
|
7
|
-
*
|
|
8
|
-
* The horde is BUILT-IN gameplay wired in `game.scene.json`: two `Spawner`s clone
|
|
9
|
-
* goblin/ghost templates, each enemy `Chase`s the player, and a `DamageOnContact`
|
|
10
|
-
* hitbox drains `Health`. The custom TypeScript is the survivor FEEL the library
|
|
11
|
-
* leaves open: `Survivor` (move + auto-attack + XP/level-up/upgrades + HUD),
|
|
12
|
-
* `Director` (ring-spawn around the player + escalation), `EnemyDrop`, `EnemyFace`.
|
|
13
|
-
*/
|
|
14
|
-
import { createGame2D, showBootFailure } from 'incanto/2d';
|
|
15
|
-
import ghostUrl from 'incanto/assets/characters/ghost.png';
|
|
16
|
-
import goblinUrl from 'incanto/assets/characters/goblin.png';
|
|
17
|
-
import knightUrl from 'incanto/assets/characters/medieval-knight.png';
|
|
18
|
-
import { Director, EnemyDrop, EnemyFace, GridFloor, Survivor } from './behaviors';
|
|
19
|
-
import sceneJson from './game.scene.json';
|
|
20
|
-
|
|
21
|
-
const MUSIC_URL = '';
|
|
22
|
-
|
|
23
|
-
const behaviors = { Survivor, Director, EnemyDrop, EnemyFace, GridFloor };
|
|
24
|
-
|
|
25
|
-
const canvas = document.querySelector('canvas') as HTMLCanvasElement;
|
|
26
|
-
|
|
27
|
-
const scene = structuredClone(sceneJson) as typeof sceneJson & {
|
|
28
|
-
assets: { knight: { url: string }; goblin: { url: string }; ghost: { url: string } };
|
|
29
|
-
};
|
|
30
|
-
scene.assets.knight.url = knightUrl;
|
|
31
|
-
scene.assets.goblin.url = goblinUrl;
|
|
32
|
-
scene.assets.ghost.url = ghostUrl;
|
|
33
|
-
|
|
34
|
-
/** Dev-only surfaces: the ☰ debug overlay, and the editor behind it. */
|
|
35
|
-
const DEBUG = import.meta.env.VITE_INCANTO_DEBUG === '1';
|
|
36
|
-
|
|
37
|
-
const game = await createGame2D({
|
|
38
|
-
debug: DEBUG,
|
|
39
|
-
// The editor's 📚 buttons, served by `incantoLibrary()` in vite.config.ts.
|
|
40
|
-
// BOTH halves are the opt-in, and this half was missing from every shipped
|
|
41
|
-
// template: the plugin alone left a vite config whose own comment promised
|
|
42
|
-
// "the agent8 asset catalog behind the 📚 buttons" and no button anywhere.
|
|
43
|
-
// Gated on the same flag, because `editor` DEFAULTS to `debug` and an object
|
|
44
|
-
// here would turn the editor on in a production build.
|
|
45
|
-
editor: DEBUG && { library: true },
|
|
46
|
-
canvas,
|
|
47
|
-
scene,
|
|
48
|
-
behaviors,
|
|
49
|
-
}).catch((e) => {
|
|
50
|
-
// Without this the player watches the loading overlay sit at 100% forever:
|
|
51
|
-
// `#loading` is removed on the line below, so anything that rejects here (no
|
|
52
|
-
// WebGL context, a scene that will not load) leaves the bar up and the reason
|
|
53
|
-
// in a console nobody opens.
|
|
54
|
-
showBootFailure(e);
|
|
55
|
-
throw e;
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
// The console handle FIRST, before any wiring of your own can throw.
|
|
59
|
-
// `game.stats()`, `game.assetErrors()`, `game.frame()` and `game.engine.log`
|
|
60
|
-
// are the entire in-page diagnostic surface, and a static build has no other.
|
|
61
|
-
// Assigned after the wiring, one mistake below took all of them with it.
|
|
62
|
-
(window as unknown as { game: typeof game }).game = game;
|
|
63
|
-
|
|
64
|
-
// And the loading overlay comes down LAST. Everything between here and there is
|
|
65
|
-
// your code; a throw in it used to leave a level that renders perfectly with no
|
|
66
|
-
// player, no error UI, and no way to ask the page what happened.
|
|
67
|
-
try {
|
|
68
|
-
if (MUSIC_URL) {
|
|
69
|
-
game.engine.music.play(MUSIC_URL, { loop: true, fadeIn: 1.5 });
|
|
70
|
-
game.engine.audio.music = 0.3;
|
|
71
|
-
}
|
|
72
|
-
} catch (e) {
|
|
73
|
-
showBootFailure(e);
|
|
74
|
-
throw e;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
document.querySelector('#loading')?.remove();
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Vanguard — a 3D THIRD-PERSON shooter built on Incanto. Move with WASD, look
|
|
3
|
-
* with the mouse (click locks the pointer), Shift to sprint, Space to jump,
|
|
4
|
-
* left-click / F to fire your hitscan rifle, R to reload, Enter to restart once
|
|
5
|
-
* the mission ends. The camera rides over
|
|
6
|
-
* your soldier's shoulder (CharacterController3D `view: 'free'`); the crosshair
|
|
7
|
-
* is where you shoot. Clear three waves of chasing enemies to SECURE THE AREA;
|
|
8
|
-
* let them drain your HP to 0 and the MISSION FAILS.
|
|
9
|
-
*
|
|
10
|
-
* The whole loop is composed from built-in gameplay behaviors wired in
|
|
11
|
-
* `game.scene.json` (third-person movement+camera, enemy AI via Chase, contact
|
|
12
|
-
* damage, WaveSpawner, Health, ScoreKeeper). The only custom TypeScript is
|
|
13
|
-
* `Shoot` (the click-to-fire hitscan + face-aim) and `HudUpdater` (the HUD +
|
|
14
|
-
* win/lose banner).
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import type { SceneJson } from 'incanto';
|
|
18
|
-
import { assetUrls, preloadUrls } from 'incanto';
|
|
19
|
-
import { createGame3D, showBootFailure } from 'incanto/3d';
|
|
20
|
-
// A bundled clip looped as low ambience (no large music files ship in the
|
|
21
|
-
// package — see incanto-audio.md). vite resolves + hashes the real file.
|
|
22
|
-
import musicUrl from 'incanto/assets/audio/spells_cast.mp3';
|
|
23
|
-
import { HudUpdater, Shoot } from './behaviors';
|
|
24
|
-
import sceneJson from './game.scene.json';
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* The sub-scenes this scene `instance:`s — `cover.scene.json` and
|
|
28
|
-
* `pillar.scene.json` — handed to the loader by path. `loadScene` never reads
|
|
29
|
-
* files; vite's `import.meta.glob` gathers every scene beside this one.
|
|
30
|
-
*/
|
|
31
|
-
const prefabs = import.meta.glob('./*.scene.json', {
|
|
32
|
-
eager: true,
|
|
33
|
-
import: 'default',
|
|
34
|
-
}) as Record<string, SceneJson>;
|
|
35
|
-
const resolveScene = (path: string): SceneJson | null => prefabs[`./${path}`] ?? null;
|
|
36
|
-
|
|
37
|
-
// The soldier is a real GLB character (base-model.glb) animated by mixamo clips
|
|
38
|
-
// (idle/walk/run/jump) — declared in the scene `assets`. Warm the HTTP cache with
|
|
39
|
-
// a progress bar before booting; the arena, enemies, SFX + music stay zero-fetch.
|
|
40
|
-
const fill = document.querySelector('#progress') as HTMLElement | null;
|
|
41
|
-
const text = document.querySelector('#progress-text') as HTMLElement | null;
|
|
42
|
-
await preloadUrls(assetUrls(sceneJson.assets), (done, total) => {
|
|
43
|
-
const pct = total > 0 ? Math.round((done / total) * 100) : 100;
|
|
44
|
-
if (fill) fill.style.width = `${pct}%`;
|
|
45
|
-
if (text) text.textContent = `${pct}%`;
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
const canvas = document.querySelector('canvas') as HTMLCanvasElement;
|
|
49
|
-
// createGame3D boots everything: register (gameplay behaviors auto-registered) →
|
|
50
|
-
// load → physics (auto; the scene has bodies) → keyboard + pointer-lock look →
|
|
51
|
-
// renderer → start. We pass the two custom behaviors.
|
|
52
|
-
/** Dev-only surfaces: the ☰ debug overlay, and the editor behind it. */
|
|
53
|
-
const DEBUG = import.meta.env.VITE_INCANTO_DEBUG === '1';
|
|
54
|
-
|
|
55
|
-
const game = await createGame3D({
|
|
56
|
-
debug: DEBUG,
|
|
57
|
-
// The editor's 📚 buttons, served by `incantoLibrary()` in vite.config.ts.
|
|
58
|
-
// BOTH halves are the opt-in, and this half was missing from every shipped
|
|
59
|
-
// template: the plugin alone left a vite config whose own comment promised
|
|
60
|
-
// "the agent8 asset catalog behind the 📚 buttons" and no button anywhere.
|
|
61
|
-
// Gated on the same flag, because `editor` DEFAULTS to `debug` and an object
|
|
62
|
-
// here would turn the editor on in a production build.
|
|
63
|
-
editor: DEBUG && { library: true },
|
|
64
|
-
canvas,
|
|
65
|
-
scene: sceneJson,
|
|
66
|
-
resolveScene,
|
|
67
|
-
behaviors: { Shoot, HudUpdater },
|
|
68
|
-
pointer: true, // pointer-lock mouse look (lockOnClick) — drives the free-view yaw/pitch
|
|
69
|
-
}).catch((e) => {
|
|
70
|
-
// Without this the player watches the loading overlay sit at 100% forever:
|
|
71
|
-
// `#loading` is removed on the line below, so anything that rejects here (no
|
|
72
|
-
// WebGL context, a scene that will not load) leaves the bar up and the reason
|
|
73
|
-
// in a console nobody opens.
|
|
74
|
-
showBootFailure(e);
|
|
75
|
-
throw e;
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
// The console handle FIRST, before any wiring of your own can throw.
|
|
79
|
-
// `game.stats()`, `game.assetErrors()`, `game.frame()` and `game.engine.log`
|
|
80
|
-
// are the entire in-page diagnostic surface, and a static build has no other.
|
|
81
|
-
// Assigned after the wiring, one mistake below took all of them with it.
|
|
82
|
-
(window as unknown as { game: typeof game }).game = game;
|
|
83
|
-
|
|
84
|
-
// And the loading overlay comes down LAST. Everything between here and there is
|
|
85
|
-
// your code; a throw in it used to leave a level that renders perfectly with no
|
|
86
|
-
// player, no error UI, and no way to ask the page what happened.
|
|
87
|
-
try {
|
|
88
|
-
// Looping background music on the music bus (a calm tense pad). The engine
|
|
89
|
-
// auto-resumes a gesture-blocked track on the first click/keypress.
|
|
90
|
-
game.engine.music.play(musicUrl, { loop: true, fadeIn: 1.5 });
|
|
91
|
-
game.engine.audio.music = 0.3;
|
|
92
|
-
|
|
93
|
-
// On-screen FIRE / JUMP buttons (mobile + desktop parity).
|
|
94
|
-
for (const [id, code] of [
|
|
95
|
-
['btn-fire', 'KeyF'],
|
|
96
|
-
['btn-jump', 'Space'],
|
|
97
|
-
] as const) {
|
|
98
|
-
const el = document.querySelector(`#${id}`);
|
|
99
|
-
el?.addEventListener('pointerdown', () => game.engine.input.handleKey(code, true));
|
|
100
|
-
el?.addEventListener('pointerup', () => game.engine.input.handleKey(code, false));
|
|
101
|
-
}
|
|
102
|
-
} catch (e) {
|
|
103
|
-
showBootFailure(e);
|
|
104
|
-
throw e;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
document.querySelector('#loading')?.remove();
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Emberwood — a 3D quest vignette showcasing the 0.8 engine surface.
|
|
3
|
-
* Talk to the Elder (UiDialogue + choices), take the quest, sprint through the
|
|
4
|
-
* north gate (goToScene fade) into a hedge-maze grove where three wolves walk
|
|
5
|
-
* A* patrol rings (findPath + PathFollow), fell them with a sword arc
|
|
6
|
-
* (Trail3D), and report back. Wind is a live synth voice (startVoice) that
|
|
7
|
-
* rises as you run; the character animates through the controller's
|
|
8
|
-
* declarative `animations` map — zero animation code.
|
|
9
|
-
*/
|
|
10
|
-
import { assetUrls, preloadUrls } from 'incanto';
|
|
11
|
-
import { createGame3D, showBootFailure } from 'incanto/3d';
|
|
12
|
-
import { BEHAVIORS } from './behaviors';
|
|
13
|
-
import villageJson from './village.scene.json';
|
|
14
|
-
|
|
15
|
-
const fill = document.querySelector('#progress') as HTMLElement | null;
|
|
16
|
-
const text = document.querySelector('#progress-text') as HTMLElement | null;
|
|
17
|
-
await preloadUrls(assetUrls(villageJson.assets), (done, total) => {
|
|
18
|
-
const pct = total > 0 ? Math.round((done / total) * 100) : 100;
|
|
19
|
-
if (fill) fill.style.width = `${pct}%`;
|
|
20
|
-
if (text) text.textContent = `${pct}%`;
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
const canvas = document.querySelector('canvas') as HTMLCanvasElement;
|
|
24
|
-
/** Dev-only surfaces: the ☰ debug overlay, and the editor behind it. */
|
|
25
|
-
const DEBUG = import.meta.env.VITE_INCANTO_DEBUG === '1';
|
|
26
|
-
|
|
27
|
-
const game = await createGame3D({
|
|
28
|
-
debug: DEBUG,
|
|
29
|
-
// The editor's 📚 buttons, served by `incantoLibrary()` in vite.config.ts.
|
|
30
|
-
// BOTH halves are the opt-in, and this half was missing from every shipped
|
|
31
|
-
// template: the plugin alone left a vite config whose own comment promised
|
|
32
|
-
// "the agent8 asset catalog behind the 📚 buttons" and no button anywhere.
|
|
33
|
-
// Gated on the same flag, because `editor` DEFAULTS to `debug` and an object
|
|
34
|
-
// here would turn the editor on in a production build.
|
|
35
|
-
editor: DEBUG && { library: true },
|
|
36
|
-
canvas,
|
|
37
|
-
scene: villageJson,
|
|
38
|
-
behaviors: BEHAVIORS,
|
|
39
|
-
pointer: true, // pointer-lock look (click the canvas)
|
|
40
|
-
}).catch((e) => {
|
|
41
|
-
// Without this the player watches the loading overlay sit at 100% forever:
|
|
42
|
-
// `#loading` is removed on the line below, so anything that rejects here (no
|
|
43
|
-
// WebGL context, a scene that will not load) leaves the bar up and the reason
|
|
44
|
-
// in a console nobody opens.
|
|
45
|
-
showBootFailure(e);
|
|
46
|
-
throw e;
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
// The console handle FIRST, before any wiring of your own can throw.
|
|
50
|
-
// `game.stats()`, `game.assetErrors()`, `game.frame()` and `game.engine.log`
|
|
51
|
-
// are the entire in-page diagnostic surface, and a static build has no other.
|
|
52
|
-
// Assigned after the wiring, one mistake below took all of them with it.
|
|
53
|
-
(window as unknown as { game: typeof game }).game = game;
|
|
54
|
-
|
|
55
|
-
// The overlay comes down LAST, after any wiring of your own. There is none in
|
|
56
|
-
// this template — when you add some, put it above this line and wrap it:
|
|
57
|
-
//
|
|
58
|
-
// try { …your wiring… } catch (e) { showBootFailure(e); throw e; }
|
|
59
|
-
//
|
|
60
|
-
// A throw between the overlay coming down and the handle going up used to leave
|
|
61
|
-
// a level that renders perfectly with no player and no error of any kind.
|
|
62
|
-
document.querySelector('#loading')?.remove();
|