@genex-ai/cli-demo 0.80.2-dev.213 → 0.84.0-dev.215

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 (25) hide show
  1. package/dist/index.js +801 -83
  2. package/package.json +1 -1
  3. package/templates/controllers/character/first-person.ts +54 -0
  4. package/templates/controllers/character/follow-camera.ts +35 -1
  5. package/templates/skills/genex-ai-character/SKILL.md +25 -5
  6. package/templates/skills/genex-ai-hud/SKILL.md +131 -36
  7. package/templates/skills/genex-ai-hud/references/masked-fill.md +19 -13
  8. package/templates/skills/genex-ai-hud/references/stage2-prompt-template.md +2 -2
  9. package/templates/skills/genex-ai-image/SKILL.md +40 -2
  10. package/templates/skills/genex-ai-menu/SKILL.md +35 -17
  11. package/templates/skills/genex-ai-model/SKILL.md +8 -0
  12. package/templates/skills/genex-ai-music/SKILL.md +142 -0
  13. package/templates/skills/genex-ai-skybox/SKILL.md +21 -5
  14. package/templates/skills/genex-ai-video/SKILL.md +13 -7
  15. package/templates/skills/genex-ai-voice/SKILL.md +151 -0
  16. package/templates/skills/genex-game-director/SKILL.md +128 -44
  17. package/templates/skills/genex-game-director/references/design-contract.md +7 -2
  18. package/templates/skills/genex-game-director/references/routing-map.md +4 -1
  19. package/templates/skills/genex-threejs-camera-direction/SKILL.md +4 -1
  20. package/templates/skills/genex-threejs-character-controller/SKILL.md +6 -1
  21. package/templates/skills/genex-threejs-character-controller/references/wiring.md +13 -2
  22. package/templates/skills/genex-threejs-creatures/SKILL.md +193 -0
  23. package/templates/skills/genex-threejs-game-ui/SKILL.md +5 -1
  24. package/templates/skills/genex-threejs-multiplayer/SKILL.md +6 -1
  25. package/templates/skills/genex-threejs-touch-controls/SKILL.md +7 -0
@@ -45,10 +45,31 @@ missing.
45
45
 
46
46
  ## 3. The design contract — DESIGN.md
47
47
 
48
- Before rendering code, write `DESIGN.md` at the project root from
49
- [references/design-contract.md](references/design-contract.md). Post a short
50
- summary in chat (the plan-message duties from `$genex-threejs-game-ui` fold
51
- into this file plus that summary). The file is the single source of truth:
48
+ **First, the design interview — before DESIGN.md is written.** Ask the
49
+ player 2–4 build-forking questions, batched in ONE round — use your
50
+ structured question / ask tool if your harness has one, with answer options
51
+ for the user. Ask only what genuinely forks the build:
52
+
53
+ - the one-line pitch, confirmed or corrected ("a co-op scythe hunt in a
54
+ ruined cathedral — right?");
55
+ - the solo / co-op / versus shape (it decides netcode and scope);
56
+ - scope ambition, when the request could honestly be read small or large
57
+ (compact arena vs. open world);
58
+ - any real ambiguity in the request itself.
59
+
60
+ Never ask about SDKs, engines, renderers, file layout, or anything
61
+ technical — those are your decisions. If the player is silent or has no way
62
+ to answer, proceed on your own stated assumptions and write each one into
63
+ DESIGN.md → Decisions as "assumed — player didn't answer"; the build never
64
+ stalls on the interview.
65
+
66
+ Then, before rendering code, write `DESIGN.md` at the project root from
67
+ [references/design-contract.md](references/design-contract.md). The moment
68
+ the file lands, post a 5–6 line summary of the contract in chat — pitch,
69
+ core loop, content counts, screens, multiplayer shape, what you build
70
+ first — and keep building immediately: the summary is information, not a
71
+ gate (the plan-message duties from `$genex-threejs-game-ui` fold into this
72
+ file plus that summary). The file is the single source of truth:
52
73
  sub-agents build against it, and after any long break it is how work resumes.
53
74
  Keep it current — decisions land in its log the moment they're made.
54
75
 
@@ -65,13 +86,24 @@ steps live in each owning skill — load it when its lane fires:
65
86
  outdoors → `$genex-ai-skybox`
66
87
  - `npx genex sfx "<prompt>"` — the core verb and every impact →
67
88
  `$genex-ai-sfx`
89
+ - `npx genex music "<prompt>"` — ONE looping instrumental gameplay track
90
+ (~90 s default; the menu reuses it quieter; settings gets Music + SFX
91
+ sliders) → `$genex-ai-music`
92
+ - `npx genex voice "<line>"` — short spoken lines: NPC barks, narrator
93
+ beats, tutorial VO (curated cast via `--voice`; keep lines short,
94
+ subtitled, skippable) → `$genex-ai-voice`
68
95
  - `npx genex image "<prompt>"` — posters, signs, sprites, decals, HUD art
69
- (`--transparent` for anything laid on a surface) `$genex-ai-image`,
96
+ (`--transparent` for anything laid on a surface; `--glass` for real-
97
+ translucency glass panels) → `$genex-ai-image`,
70
98
  `$genex-ai-hud`
71
- - `npx genex video "<prompt>"` — in-world screens, billboards, an animated
72
- menu backdrop (`--loop` for seamless) → `$genex-ai-video`, `$genex-ai-menu`
73
- - `npx genex character "<prompt>"`a custom playable humanoid (REQUIRED
74
- player approvals§7) `$genex-ai-character`
99
+ - `npx genex video "<prompt>"` — in-world screens and billboards (`--loop`
100
+ for a seamless in-world loop) → `$genex-ai-video`; the animated menu
101
+ backdrop is its own lane`$genex-ai-menu`'s `--frame` flow, never `--loop`
102
+ - `npx genex character "<prompt>"` the game's themed character (approval
103
+ flow — §7) → `$genex-ai-character`
104
+ - `npx genex creature "<desc>"` — a rigged enemy/creature in one shot
105
+ (biped-shaped bodies only — the creatures skill routes the rest to
106
+ static + procedural) → `$genex-threejs-creatures`
75
107
  - `npx genex controller character|car|drone|touch|quality` and
76
108
  `npx genex animations search "<intent>"` — ready-made, tuned movement and
77
109
  motion; never write movement physics from scratch →
@@ -89,6 +121,12 @@ variation); prefer these generators for concrete, describable, photoreal
89
121
  assets — they complement each other. Assets you didn't plan don't exist: if
90
122
  the menu has a lane this game needs, put a row in the Assets table.
91
123
 
124
+ **No eternal `proposed`.** At every preview and publish, walk the Assets
125
+ table and resolve every `proposed` row — promote it to `planned` (and
126
+ enqueue it when its turn comes) or cancel it, saying which in one visible
127
+ line ("cancelled: UI hover sfx — out of scope for v1"). A row parked at
128
+ `proposed` across a whole session is a decision you didn't make.
129
+
92
130
  **Generate a core asset set by default — don't wait to be asked.** For any
93
131
  game that needs concrete objects or surfaces, decide a small core set from the
94
132
  game IDEA — and from the Content lines when there are any (locations and the
@@ -102,7 +140,9 @@ each in as it lands, with a procedural placeholder until then:
102
140
  - the **hero model** the player controls or chases (`npx genex model`),
103
141
  - one key **texture** for the ground/main surface (`--terrain` for ground),
104
142
  - a **skybox** when the scene is outdoors,
105
- - a **sfx** or two for the core action and its feedback.
143
+ - a **sfx** or two for the core action and its feedback,
144
+ - one looping **music** track for the gameplay bed (`npx genex music`,
145
+ ~90 s; the menu reuses it at lower volume).
106
146
 
107
147
  Skip generation only for purely abstract/geometric games. For three.js
108
148
  questions no skill covers, use the official three.js documentation
@@ -207,36 +247,59 @@ agent: you stay the director.
207
247
  enqueues. (Whoever wires the HUD after a worker finishes follows
208
248
  `$genex-ai-hud`'s handoff rule: read the produced mask/bbox JSON from disk,
209
249
  never wire from a prose summary.)
210
- - Do NOT spawn workers to write extra test suites or audits one
211
- verification worker at most, running the smoke checks the scaffold prompt
212
- already requires.
213
-
214
- ## 7. A custom playable character (Meshy)approvals are the product
215
-
216
- Use the existing VRM + UAL character controller by default
217
- (`npx genex controller character`). Use `npx genex character` when the game
218
- needs a custom generated humanoid or an action unavailable in UAL. Before
219
- generating a Meshy character, discuss two or three visual directions. When the
220
- user names a visual reference, inspect references before writing the concept
221
- prompt. Recommend a neutral A-pose for characters that will be rigged.
222
-
223
- Generate concept images first and show the actual images to the user. Do not
224
- start Image-to-3D until the user explicitly selects a candidate. Generate
225
- exactly three concepts, all neutral A-pose; never use a dynamic concept pose
226
- or silently fall back to T-pose. Warn that held, slung, or overlapping props
227
- and straps can fuse into the body or obscure limbs, and recommend separate
228
- gameplay props. Only after the explicit choice, run
229
- `npx genex character preview <concept-id> --candidate <1|2|3> --user-approved`.
250
+ - Do NOT spawn workers to write extra test suites, audits, or verification
251
+ passes the per-milestone smoke pass is yours, the director's, and it is
252
+ ONE pass (§8; the scaffold prompt owns the ceilings).
253
+ - If you build a module the table planned for a sub-agent inline, say why in
254
+ one line in chat ("built enemies inlinethe arena worker was still
255
+ holding the only free slot"). The table is accountability, not ceremony —
256
+ inline can be the right call.
257
+
258
+ ## 7. The game's character (Meshy) themed by default
259
+
260
+ **A themed character is the DEFAULT for any game whose protagonist is
261
+ VISIBLE** third-person, or first-person with co-op/remote players who see
262
+ each other. Put its row in the Assets table up front and install the
263
+ VRM + UAL controller (`npx genex controller character`) as the instant
264
+ placeholder. The VRM stays the FINAL character only for games with no
265
+ themed protagonist to sell (a generic exploration toy, a faceless solo
266
+ first-person game say which in one line). A capsule or hand-built
267
+ primitive standing in for a person is never a shipped state, for the local
268
+ player or a remote one.
269
+
270
+ **The default lane has ONE user stop, and it rides the concept review.**
271
+ When the user names a visual reference, inspect references before writing
272
+ the concept prompt. Generate exactly three concepts, all neutral A-pose;
273
+ never use a dynamic concept pose or silently fall back to T-pose. Warn that
274
+ held, slung, or overlapping props and straps can fuse into the body or
275
+ obscure limbs, and recommend separate gameplay props. Show the actual
276
+ images in the SAME beat as the game-concept keep-or-change question — one
277
+ review, two picks. The player's pick carries the lane end to end:
278
+ `npx genex character preview <concept-id> --candidate <1|2|3> --user-approved`,
279
+ then finalize below. **If the player hasn't picked by the time the
280
+ character blocks progress (or ~10 minutes), pick the strongest candidate
281
+ yourself, say which and why in chat, and proceed** — this auto-proceed is
282
+ owner-ratified platform policy (2026-07-23), not an agent liberty; record
283
+ it in DESIGN.md → Decisions ("auto-picked candidate 2 — cleanest
284
+ silhouette; player away").
230
285
 
231
286
  Meshy Image-to-3D first produces an unremeshed high-detail model. Show its
232
- front, back, left, and right views and report its measured face count. Preserve
233
- that model in R2. Before rigging, ask the user to approve a separate
234
- 10,000-face triangle remesh. The 10k remesh—not the high-detail source—is
235
- rigged and animated. Keep every pre-animation generation in the selected
236
- neutral A-pose. Wait for that explicit approval before
287
+ front, back, left, and right views and report its measured face count.
288
+ Preserve that model in R2. The 10,000-face triangle remesh—not the
289
+ high-detail source—is rigged and animated. In the default lane the remesh
290
+ proceeds on the same authorization as the pick (say it plainly: "building
291
+ the 10,000-face rigging copy now"):
237
292
  `npx genex character finalize <preview-id> --user-approved --approve-remesh 10000 [--animation <action-id>…]`.
238
- (`npx genex character "<prompt>" --direct-text` is the explicit legacy
239
- one-shot path, not a substitute for these approvals.)
293
+ Keep every pre-animation generation in the selected neutral A-pose.
294
+
295
+ **When the user themselves asked for a custom character** (an explicit
296
+ custom-character request, not the game default), the ceremony is two
297
+ separate stops and the approvals are the product: do not start Image-to-3D
298
+ until they explicitly select a candidate, and before rigging ask them to
299
+ approve the separate 10,000-face triangle remesh — wait for that explicit
300
+ approval before finalize. (`npx genex character "<prompt>" --direct-text`
301
+ is the explicit legacy one-shot path, not a substitute for these
302
+ approvals.)
240
303
 
241
304
  Load `$genex-ai-character`, search Meshy actions first with
242
305
  `npx genex animations search "<intent>" --json`, and use returned action IDs;
@@ -248,13 +311,34 @@ Before handoff, visibly check idle, walk, run, crouch-idle, crouch-move, and
248
311
  jump — shoulders, elbows, wrists, hands, both leg cycles, and feet — and press
249
312
  every control the HUD advertises.
250
313
 
251
- ## 8. Fresh-eyes review before publish
252
-
253
- Take the game's current screenshots (desktop and phone sizes) and hand them,
254
- with DESIGN.md only, to a fresh reviewer — a sub-agent if you have one,
255
- otherwise re-read them yourself adversarially, looking to refute "it's done":
256
- untextured surfaces, a bare HUD, missing screens, Content lines not in the
257
- game, Assets rows never flipped to `wired`. Fix or honestly report what it
314
+ ## 8. Verificationthe smoke pass's captures grow with the build
315
+
316
+ The per-milestone smoke pass and its ceilings belong to the scaffold prompt
317
+ (ONE pass per milestone, never test suites, never re-verify after cosmetic
318
+ tweaks) this section only defines WHAT that one pass captures once the
319
+ relevant piece exists:
320
+
321
+ - **Always:** the gameplay screenshot + the main controls responding the
322
+ right way (the scaffold prompt's baseline).
323
+ - **Once the generated HUD is wired:** take the gameplay screenshot AFTER
324
+ taking damage once, with an enemy in frame facing the player. A full-HP
325
+ shot cannot show a broken meter (a painted trough hides behind a 100%
326
+ fill), and an enemy you never faced head-on may be looking sideways at
327
+ everyone.
328
+ - **Once the menu video is wired:** watch one full loop cycle as rendered
329
+ (`$genex-ai-menu`'s seam check). A metadata probe can't see a seam, a
330
+ hidden video, or a leftover panel covering it.
331
+
332
+ Judge each capture against DESIGN.md once, fix only what is visibly broken,
333
+ and move on — the captures are eyes, not a test suite.
334
+
335
+ **Fresh eyes before publish.** The pre-publish check is just the last
336
+ milestone's pass, plus this: take the game's current screenshots (desktop
337
+ and phone sizes) and hand them, with DESIGN.md only, to a fresh reviewer —
338
+ a sub-agent if you have one, otherwise re-read them yourself adversarially,
339
+ looking to refute "it's done": untextured surfaces, a bare HUD, missing
340
+ screens, Content lines not in the game, Assets rows never flipped to
341
+ `wired`, `proposed` rows never resolved. Fix or honestly report what it
258
342
  finds; never publish over an unacknowledged gap.
259
343
 
260
344
  ## 9. Say it straight
@@ -13,7 +13,10 @@ Rules the director enforces about this file:
13
13
  sections as decisions land and keep it current (stale is worse than short).
14
14
  - **The Modules table is the delegation contract**: one row per independent
15
15
  lane, and a row's "Owns files" set never overlaps another row's. One writer
16
- per file.
16
+ per file. "Sub-agent when available" stays flexible — but if a
17
+ planned-sub-agent module gets built inline, the agent says why in one line.
18
+ Verification is never a module row: the milestone smoke pass belongs to the
19
+ director (the scaffold prompt owns its ceilings).
17
20
  - **The Assets table is the budget**: the asset list falls out of Content
18
21
  (enemies → models, an arena → a ground texture, outdoors → a skybox).
19
22
  Status flow per row: `proposed → planned → generating (id) → landed (URL) →
@@ -22,6 +25,8 @@ Rules the director enforces about this file:
22
25
  flips statuses and never enqueues. Re-rolls follow the player's notes only.
23
26
  The `Wired?` column exists because "generated but never wired in" is the
24
27
  most common way finished art gets lost — a row isn't done at `landed`.
28
+ And no eternal `proposed`: at every preview/publish, every `proposed` row
29
+ gets promoted or cancelled with one visible line — never silently parked.
25
30
  - Shrinking any Content line is a question to the player first, never a
26
31
  silent cut.
27
32
 
@@ -63,6 +68,7 @@ References: <2–3 named games> · Menu archetype: <name>
63
68
  | Concept + HUD | image | landed → <URL> (candidate <n>) | n/a |
64
69
  | <main surface> | texture | generating (<id>) | — |
65
70
  | <hero model> | model | planned | — |
71
+ | Background music | music | planned (one ~90s looping track)| — |
66
72
  | Menu still+video | image+video | blocked on concept yes → queued | — |
67
73
  Status flow: proposed → planned → generating (id) → landed (URL) → wired.
68
74
  (Optionally note the prompt gist per row — it makes style-change re-rolls one
@@ -84,7 +90,6 @@ click (when a Play screen exists).
84
90
  | Quests & dialogue data | src/content/** | sub-agent when available | counts match Content lines |
85
91
  | Enemies/AI | src/enemies/** | sub-agent when available | roster matches Content |
86
92
  | HUD chain (style-dependent) | src/ui/** | sub-agent AFTER concept yes | all screens from Screens & UI |
87
- | Verification | (no source files) | one sub-agent max | smoke check notes per milestone |
88
93
 
89
94
  ## Decisions & changes
90
95
  - <date> — <one-liner per decision, including anything the player said no or
@@ -21,7 +21,9 @@ Three.js release or branch, and do not blindly copy demo architecture.
21
21
  | --- | --- |
22
22
  | shot composition, chase/side/orbit rigs, camera handoffs, projection ownership, pointer look, mouse-aimed action (shooter, FPS/first-person, sniper, turret, crosshair/reticle), mouse-look, hand-rolled steering/pan/look input signs (screen-direction contract), floating origins | `$genex-threejs-camera-direction` |
23
23
  | on-foot player movement: walk/run/jump/crouch, third-person character, slopes, stairs, moving platforms, personal VRM animation, directional locomotion, transitions, action motion | `$genex-threejs-character-controller` |
24
- | a custom generated playable humanoid or Meshy animation coverage beyond UAL: reference-informed A-pose concepts, explicit candidate + 10k-remesh approvals, exact action IDs, same-rig adapter | `$genex-ai-character` + `$genex-threejs-character-controller` |
24
+ | the game's themed character the DEFAULT whenever the protagonist is visible (third-person, or first-person with co-op/remote players); one user stop riding the concept review, owner-ratified auto-pick on silence (director §7) — or Meshy animation coverage beyond UAL: reference-informed A-pose concepts, exact action IDs, same-rig adapter | `$genex-ai-character` + `$genex-threejs-character-controller` |
25
+ | remote player bodies in multiplayer — NEVER hand-built primitives: the themed character model in themed games, the player's `p.avatarUrl` VRM otherwise | `$genex-threejs-multiplayer` + `$genex-threejs-character-controller` |
26
+ | the game has enemies, NPCs, or creatures — **load whenever an enemy roster exists**: rigged bipeds via `npx genex creature`, static + procedural motion for other body shapes, plus the mechanical floor every enemy owes (collider, verified facing, hit reaction, death moment) | `$genex-threejs-creatures` |
25
27
  | the player drives or flies something: cars, drones, vehicle physics, gearbox, enter/exit between character and vehicle | `$genex-threejs-vehicle-controllers` |
26
28
  | playable on phones: touch/mobile input for any game — joystick, virtual buttons, drag zones, per-genre touch recipes, rotate-device overlay — wired by default for every NEW game when a recipe fits (skip with a one-line reason) | `$genex-threejs-touch-controls` |
27
29
  | phone-survivable rendering — device tiers, DPR/shadow/post budgets, the runtime quality governor, per-tier asset rungs for generated skyboxes/textures, the Quality picker, dispose-on-swap discipline — **mandatory for every game at boot wiring** | `$genex-threejs-adaptive-quality` |
@@ -53,6 +55,7 @@ Three.js release or branch, and do not blindly copy demo architecture.
53
55
  | the 2D interface — HUD, menus, pause/win/lose screens, loaders, lobby, on-screen text and buttons, UI state flow — **mandatory for every game**, and its "Plan the UI first" gate runs right after the concept is locked | `$genex-threejs-game-ui` |
54
56
  | a cinematic menu — main menu/title/pause/victory/defeat/lobby/credits with a looping generated video backdrop behind DOM buttons | `$genex-ai-menu` |
55
57
  | a cohesive art-directed HUD — generated sprite set (matched frames, masks, icons in one style) wired with masked fills | `$genex-ai-hud` |
58
+ | background music — the looping instrumental track under gameplay and menu (default ONE ~90 s track; Music + SFX sliders in settings) | `$genex-ai-music` |
56
59
  | the game works but feels flat, floaty, or unresponsive: input response, acceleration curves, camera shake, hit feedback, hitstop, cooldowns, difficulty ramp, fail/retry loop | `$genex-threejs-game-feel` |
57
60
  | realtime multiplayer: movement sync, a shared ball/NPC, host-run scores/enemies, shots/emotes, persistence | `$genex-threejs-multiplayer` |
58
61
  | player identity, sign-in, guests, saves/progress, per-player state, a shared persistent world, leaderboards — **mandatory for every game** | `$genex-threejs-embed-auth` |
@@ -45,7 +45,10 @@ the build plan:
45
45
  - **MANDATORY** — first-person of any kind (FPS, walking sim, horror) and any
46
46
  mouse-aimed action (third-person shooter, turret/range). Lock is on by default;
47
47
  leave it on. Shipping this unlocked is a defect, not a style choice — validation
48
- fails it.
48
+ fails it. For first-person on the bundled controller, use the REAL mode —
49
+ `firstPerson: true` on `FollowCamera` (eye-height target, no zoom, no
50
+ collision pullback) + `setFirstPersonBody()` to hide the local body while
51
+ keeping its shadow — never a pinned tiny follow distance.
49
52
  - **HIGHLY RECOMMENDED** — third-person free-camera action/adventure (the default
50
53
  `genex controller character` game). On by default; leave it on. Opt out with
51
54
  `pointerLockAim: false` only for a stated reason (a cursor-heavy UI at the core
@@ -316,7 +316,12 @@ they leave) — move it with the interpolator from `$genex-threejs-multiplayer`,
316
316
  and **never** create a rigid body, a `CharacterController`, or any physics for
317
317
  it. Simulating remote players' physics locally guarantees divergence — every
318
318
  client would compute a different world. Never render every remote with your
319
- own avatar file: players picked their looks, show them.
319
+ own avatar file: players picked their looks, show them. And a remote player's
320
+ body is **never hand-built primitives** (no capsule-plus-cone "person"): in a
321
+ themed game remotes wear the SAME themed character model the local player
322
+ uses; otherwise they wear their `p.avatarUrl` VRM. First-person games are not
323
+ exempt — the local player may be invisible to themselves
324
+ (`setFirstPersonBody`), but every remote is a full character on screen.
320
325
 
321
326
  - **Publish `character.netState()`** on the fixed 10–20 Hz tick (never per frame):
322
327
  `room.me.set(character.netState())`. It bundles the network-safe position, a four-number
@@ -118,8 +118,19 @@ Rules that matter:
118
118
  non-recursive) and must never include the character or vehicle meshes — the
119
119
  rays start at the character's head and would hit them every frame. The array
120
120
  is public — mutate it after level loads.
121
- - `minDistance` defaults to 0.02, so zooming all the way in is effectively
122
- first-person; clamp with `minDistance`/`maxDistance` for your scale.
121
+ - **First-person is a real mode, not a zoom trick**: pass
122
+ `firstPerson: true` (or flip the public `followCam.firstPerson` field at
123
+ runtime) — the camera sits AT the follow target and looks out along the
124
+ aim direction, wheel zoom is ignored, and collision pullback is skipped.
125
+ Feed the follow target the character's EYE height (~1.6–1.7 m up the
126
+ capsule, not the head-top orbit anchor), hide the local body with
127
+ `setFirstPersonBody(model, true)` (`first-person.ts` — keeps the shadow,
128
+ clones materials so shared remote-player materials are untouched), and
129
+ parent the viewmodel (held weapon/hands) to the CAMERA so it moves with
130
+ the view. Pointer lock stays mandatory (`$genex-threejs-camera-direction`).
131
+ Do NOT fake first-person by pinning a tiny follow distance — the old
132
+ 0.02-min-distance trick leaves collision pullback and zoom live, and both
133
+ fight the player.
123
134
  - Feel: `smoothTime` (0.05 snappy → 0.25 cinematic, default 0.1),
124
135
  `initialDistance` (default 4), `initialAzimuthAngle` (default `Math.PI` —
125
136
  camera starts behind a +Z-facing character).
@@ -0,0 +1,193 @@
1
+ ---
2
+ name: genex-threejs-creatures
3
+ description: Build enemies and creatures that hold up in play — rigged Meshy bipeds via `npx genex creature` or static models with procedural motion, plus the mechanical floor every enemy owes the player regardless of rigging - a physics collider (no walking through bodies), verified facing, hit reactions, and a death moment. Load whenever the game has enemies, NPCs, or creatures.
4
+ ---
5
+
6
+ # Genex Three.js · Creatures & Enemies
7
+
8
+ An enemy the player can walk through, that faces sideways, and that dies by
9
+ vanishing is the fastest way for a finished-looking game to feel broken. This
10
+ skill owns the enemy-quality floor: which generation lane each creature takes,
11
+ and the four mechanical rules that apply to ALL of them.
12
+
13
+ ## Choose the lane per creature — by body shape
14
+
15
+ **Meshy rigs biped-shaped bodies only.** This is a measured platform limit
16
+ (live-tested 2026-07-23), and it starts at the MODEL stage: a prompt for a
17
+ four-legged stance comes back standing upright, and wings get no bones (they
18
+ skin to the spine/arms and move rigidly — a wing flap is impossible through
19
+ the rig). Route by silhouette:
20
+
21
+ - **Biped-shaped** (werewolf, orc, skeleton, gargoyle, zombie, knight — two
22
+ legs, two arms, upright): the **rigged lane** below. Real skeleton, real
23
+ library animations. This is the DEFAULT for every enemy that fits it.
24
+ - **Everything else** (true quadrupeds, serpents, swarms, fliers mid-flight,
25
+ blobs): the **static + procedural lane** — `npx genex model` for the body,
26
+ motion authored in code. Say it honestly in the Assets table:
27
+ `hound: static + procedural — Meshy rigs bipeds only`. Never pretend a
28
+ procedural creature is rigged.
29
+
30
+ ## The rigged lane — `npx genex creature`
31
+
32
+ One shot, no approval ceremony (an enemy is production scenery, not the
33
+ player's identity piece — the themed PLAYER character keeps its review beat,
34
+ `$genex-ai-character`):
35
+
36
+ ```bash
37
+ # 1. Find real clip ids first — never invent them:
38
+ npx genex animations search "zombie walk" --json
39
+ npx genex animations search "melee attack" --json
40
+ npx genex animations search "death backward" --json
41
+
42
+ # 2. One command: model → rig → bind those clips (enqueue and keep building):
43
+ npx genex creature "hulking bone seraph, tattered wing membranes, upright stance" \
44
+ --animation <walk-id> --animation <attack-id> --animation <death-id> --no-wait
45
+ ```
46
+
47
+ Each creature is one Assets-table row (visible spend — the usual budget
48
+ rules). The result is a rigged GLB whose clips play on a standard
49
+ `THREE.AnimationMixer`; Meshy limb rotations play unchanged — never apply
50
+ post-mixer limb corrections. Prompt the body UPRIGHT and unpropped (held
51
+ props fuse into bodies); prompt "facing the viewer" but never trust it —
52
+ facing is verified below.
53
+
54
+ ### State → clip wiring (one mixer per creature)
55
+
56
+ ```ts
57
+ import * as THREE from "three";
58
+
59
+ interface CreatureRig {
60
+ root: THREE.Object3D;
61
+ mixer: THREE.AnimationMixer;
62
+ actions: Record<"walk" | "attack" | "hit" | "death", THREE.AnimationAction>;
63
+ current?: THREE.AnimationAction;
64
+ }
65
+
66
+ function play(rig: CreatureRig, name: keyof CreatureRig["actions"], fade = 0.18): void {
67
+ const next = rig.actions[name];
68
+ if (rig.current === next) return;
69
+ next.reset();
70
+ if (name === "attack" || name === "hit" || name === "death") {
71
+ next.setLoop(THREE.LoopOnce, 1);
72
+ next.clampWhenFinished = true; // death holds its last frame
73
+ }
74
+ if (rig.current) next.crossFadeFrom(rig.current, fade, false);
75
+ next.play();
76
+ rig.current = next;
77
+ }
78
+ // drive from the enemy state machine: chase → play(rig, "walk");
79
+ // windup+strike → play(rig, "attack"); damaged → play(rig, "hit");
80
+ // hp <= 0 → play(rig, "death") and only AFTER the clip finishes, run the
81
+ // death VFX moment (embers/dissolve) — animation first, particles second.
82
+ // mixer.update(dt) every frame; one mixer per creature, clips cloned per
83
+ // instance (THREE.AnimationUtils / SkeletonUtils.clone for shared GLBs).
84
+ ```
85
+
86
+ ## The mechanical floor — ALL enemies, rigged or not
87
+
88
+ ### 1. A collider — the player never walks through a body
89
+
90
+ An enemy that is only a `THREE.Group` is a ghost. Give every enemy a physics
91
+ presence. The recipe (Rapier, matching `$genex-threejs-physics-rapier` and
92
+ the bundled character controller):
93
+
94
+ ```ts
95
+ import RAPIER from "@dimforge/rapier3d-compat";
96
+
97
+ /** One kinematic capsule per enemy: the CONTROLLER collides with it (no
98
+ * walk-through) but the enemy's own movement stays script-driven — AI code
99
+ * keeps teleport-free authority via setNextKinematicTranslation. */
100
+ function addEnemyCollider(world: RAPIER.World, e: { root: THREE.Object3D; halfHeight: number; radius: number }) {
101
+ const body = world.createRigidBody(
102
+ RAPIER.RigidBodyDesc.kinematicPositionBased().setTranslation(
103
+ e.root.position.x, e.root.position.y + e.halfHeight + e.radius, e.root.position.z,
104
+ ),
105
+ );
106
+ world.createCollider(RAPIER.ColliderDesc.capsule(e.halfHeight, e.radius), body);
107
+ return body;
108
+ }
109
+ // every frame AFTER the AI moves the root:
110
+ // body.setNextKinematicTranslation({ x, y: y + halfHeight + radius, z });
111
+ // Size from the model's real bounding box (new THREE.Box3().setFromObject),
112
+ // not guessed numbers. Gameplay range tests (aggro, melee reach) keep using
113
+ // your own distance math — the collider exists so BODIES are solid.
114
+ ```
115
+
116
+ If the game has no physics world at all, the minimal honest fallback is a
117
+ controller-side overlap resolve: each frame, push the player out of each
118
+ enemy's XZ radius (`if (dist < r) player.position.addScaledVector(away, r - dist)`).
119
+ Solid beats elegant.
120
+
121
+ ### 2. Verified facing — walk in front of each enemy type once
122
+
123
+ Generated models are NOT reliably authored front-toward-+Z, and a
124
+ `lookAt`-driven enemy with a sideways-authored model walks sideways forever —
125
+ invisible from behind-the-player camera angles, glaring head-on. Two steps:
126
+
127
+ ```ts
128
+ /** Wrap the GLB so +Z is the FORWARD your code can trust: rotate the child
129
+ * inside the wrapper until its face agrees, then aim only the wrapper. */
130
+ function wrapForward(model: THREE.Object3D, yawCorrection: number): THREE.Group {
131
+ const wrapper = new THREE.Group();
132
+ model.rotation.y = yawCorrection; // 0, ±Math.PI/2, or Math.PI — per MODEL, found by looking
133
+ wrapper.add(model);
134
+ return wrapper; // enemy code does wrapper.lookAt(...) / aims the wrapper only
135
+ }
136
+ ```
137
+
138
+ The verification is human and takes ten seconds per enemy TYPE: stand in
139
+ front of it once — it must face you. This is part of the milestone smoke
140
+ pass once enemies exist (an enemy in frame, facing the player). Set the
141
+ `yawCorrection` constant per model and move on.
142
+
143
+ ### 3. Hit reaction — damage reads on the body
144
+
145
+ Rigged: the `hit` clip above. Procedural: a 100–150 ms flinch — scale pulse
146
+ (`1 → 0.92 → 1`), a brief emissive/color flash, and a small recoil along the
147
+ hit direction. Pair it with the HUD hit marker; a bullet that changes nothing
148
+ on the body reads as a miss even when the numbers moved.
149
+
150
+ ### 4. A death moment — never blink out of existence
151
+
152
+ Rigged: play `death`, hold the final frame (~0.5 s), THEN dissolve/embers and
153
+ remove. Procedural: collapse (scale Y toward 0 with a topple rotation) into
154
+ the same dissolve. Either way the death VFX is a `$genex-threejs-procedural-vfx`
155
+ moment that EARNS its beat (the target dissolves and awards score) — one
156
+ pooled burst, not a particle bath.
157
+
158
+ ## Procedural motion recipes (the static lane, done well)
159
+
160
+ Give an unrigged body three layered motions — enough life that "static +
161
+ procedural" is a real choice, not a downgrade: a **gait bob** (body
162
+ `position.y += sin(t * stride) * 0.05` with a slight roll for quadrupeds), a
163
+ **lunge stretch** (scale Z up 8% during attack windup, snap back on strike),
164
+ and an **idle sway** (low-amplitude yaw/pitch noise so nothing stands
165
+ morgue-still). Author them against the wrapper from rule 2 so facing math
166
+ stays clean. `$genex-threejs-procedural-animation` has the timeline tools for
167
+ anything staged.
168
+
169
+ ## Multiplayer
170
+
171
+ Enemies are host-simulated shared objects (`$genex-threejs-multiplayer` —
172
+ the host owns `room.objects` for every enemy; remotes render interpolated
173
+ state). The collider rule applies on every client — bodies are solid locally
174
+ even when the HOST owns the movement; clip/state changes ride the shared
175
+ object's state field, never a per-frame broadcast.
176
+
177
+ ## Troubleshooting
178
+
179
+ - **"Out of credits" (`insufficient_credits`)** — tell the user the facts the
180
+ CLI printed (balance, cost, refill), continue with a procedural-placeholder
181
+ enemy body, and mark the spot with
182
+ `// TODO(genex): regenerate when credits refill`. Do not stop the session.
183
+ - **"Email not verified" (`email_verification_required`)** — hand over the
184
+ verify link the CLI printed, wait, re-run.
185
+ - **The creature came back standing when you wanted four legs** — that is the
186
+ documented platform limit, not a bad roll: re-rolling the prompt will not
187
+ produce a rigged quadruped. Switch that creature to the static + procedural
188
+ lane and say so in the Assets table.
189
+ - **Clips look wrong on the body** (arms clip the torso on a bulky model) —
190
+ pick a different library action id (`animations search`); never patch limbs
191
+ post-mixer.
192
+ - **Every instance animates in sync** — you shared one mixer or one clip
193
+ instance; clone per creature (`SkeletonUtils.clone` + a fresh mixer each).
@@ -27,7 +27,7 @@ in another.
27
27
  | Pause | always — opens on the Escape key | 1 — menu backdrop under a dark overlay |
28
28
  | Fail / retry | always | 1 — a *graded* variant of the menu screen |
29
29
  | Win / next | always | 1 — graded variant, warm |
30
- | Settings | always — every game carries the Quality picker (Auto/Low/Medium/High, `$genex-threejs-adaptive-quality`), plus whatever else it has to set | 1 |
30
+ | Settings | always — every game carries the Quality picker (Auto/Low/Medium/High, `$genex-threejs-adaptive-quality`), and any game with generated audio carries **Music + SFX volume sliders** (persisted, applied live; music default 0.30, sfx ~0.7 — `$genex-ai-music`; a paid track with no volume control is a failure mode), plus whatever else it has to set | 1 |
31
31
  | Lobby / waiting | multiplayer only | 1 over the menu backdrop |
32
32
  | HUD | always | 2 — generated sprite HUD (`$genex-ai-hud`), enqueued at this gate for EVERY game; plain CSS is the placeholder until the sprites land, never the final HUD |
33
33
 
@@ -531,6 +531,10 @@ architecture and consume the shared style brief.
531
531
  text or padding, a lost focus ring or glow, a jagged aliased edge, or a
532
532
  border/frame that stops at the cut instead of following it — the
533
533
  technique is fine; the sloppy cut is the defect.
534
+ - A plate shaped by `npx genex ui plate` (the frame's traced silhouette as
535
+ the plate's `mask-image`) is the fix for shaped backing — see
536
+ `$genex-ai-hud`'s silhouette-plate rule; a bare rounded rectangle behind
537
+ generated art is the defect below.
534
538
  - A rectangular semi-transparent plate protruding past an opaque/angular
535
539
  widget frame — a dark box floating over the scene. The frame's own art is
536
540
  the backing; a plate is only for bare-text/outline widgets and stays inside
@@ -541,7 +541,12 @@ fights (many writers). A ball on `objects` glides and has one owner. That's the
541
541
  `loadVrmClone(p.avatarUrl || "./assets/avatar.vrm")` (the vendored loader's shared-GPU clone:
542
542
  N remotes share one set of geometry/textures instead of re-parsing per player — retarget
543
543
  clips once on `loadVrmClone.base(url)` and play them on each clone's own mixer); never
544
- publish avatar URLs through `me.set`. On phone tiers, animate and fully draw only the
544
+ publish avatar URLs through `me.set`. **A remote player's body is NEVER hand-built
545
+ primitives** (no capsule + cone "person" — the single most common shipped co-op defect):
546
+ a themed game renders remotes with the SAME themed character model the local player
547
+ uses; everything else renders `p.avatarUrl` VRMs. This applies with full force to
548
+ first-person games — the local player may be invisible to themselves, but every
549
+ remote hunter/partner is a full character on screen. On phone tiers, animate and fully draw only the
545
550
  nearest `tier.remoteAvatarCap` remotes (`$genex-threejs-adaptive-quality`) — freeze the
546
551
  mixer and billboard or hide the rest; a room allows up to 64 players and 64 live avatars
547
552
  is a real phone memory kill on its own.
@@ -149,6 +149,13 @@ z-order stays: drag zone (5) under joystick/buttons (10) under pause menus.
149
149
  - **Safe-area insets are built in** — default positions clear notches and the
150
150
  home indicator. If you position widgets yourself near screen edges, keep
151
151
  `env(safe-area-inset-*)` in the calc.
152
+ - **Viewport meta is a prerequisite** — every `env(safe-area-inset-*)` value is
153
+ silently **0** unless the page's viewport meta carries `viewport-fit=cover`.
154
+ Ship `<meta name="viewport" content="width=device-width, initial-scale=1,
155
+ viewport-fit=cover">` in the game's own `index.html`: the platform edge-injects
156
+ a default for published games, but the local dev server doesn't go through
157
+ that edge — without your own meta, widgets hug the notch in local testing
158
+ and look different from production.
152
159
  - **The drag zone swallows its touches** — taps inside it don't reach the
153
160
  canvas. If the game also needs taps there (tap to shoot), read them from the
154
161
  zone (`onChange` + a small-movement threshold) or shrink the zone.