@genex-ai/cli-demo 0.81.0-dev.214 → 0.85.0-dev.216
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/README.md +9 -7
- package/dist/index.js +2623 -1684
- package/package.json +1 -1
- package/templates/controllers/character/first-person.ts +54 -0
- package/templates/controllers/character/follow-camera.ts +35 -1
- package/templates/skills/genex-ai-character/SKILL.md +25 -5
- package/templates/skills/genex-ai-hud/SKILL.md +175 -63
- package/templates/skills/genex-ai-hud/references/masked-fill.md +19 -13
- package/templates/skills/genex-ai-hud/references/stage1-prompt-template.md +42 -5
- package/templates/skills/genex-ai-hud/references/stage2-prompt-template.md +7 -3
- package/templates/skills/genex-ai-image/SKILL.md +40 -2
- package/templates/skills/genex-ai-menu/SKILL.md +47 -22
- package/templates/skills/genex-ai-model/SKILL.md +8 -0
- package/templates/skills/genex-ai-music/SKILL.md +142 -0
- package/templates/skills/genex-ai-skybox/SKILL.md +21 -5
- package/templates/skills/genex-ai-video/SKILL.md +13 -7
- package/templates/skills/genex-ai-voice/SKILL.md +151 -0
- package/templates/skills/genex-game-director/SKILL.md +183 -58
- package/templates/skills/genex-game-director/references/design-contract.md +40 -10
- package/templates/skills/genex-game-director/references/routing-map.md +44 -29
- package/templates/skills/genex-threejs-camera-direction/SKILL.md +4 -1
- package/templates/skills/genex-threejs-character-controller/SKILL.md +25 -1
- package/templates/skills/genex-threejs-character-controller/references/wiring.md +13 -2
- package/templates/skills/genex-threejs-creatures/SKILL.md +201 -0
- package/templates/skills/genex-threejs-game-ui/SKILL.md +79 -71
- package/templates/skills/genex-threejs-multiplayer/SKILL.md +6 -1
- package/templates/skills/genex-threejs-visual-validation/SKILL.md +9 -4
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Stage 1 prompt template — the game concept: full-HUD mockup
|
|
2
2
|
|
|
3
|
-
Fill the
|
|
4
|
-
`npx genex image "<filled prompt>" --size 2560x1440 --quality high
|
|
3
|
+
Fill the placeholders, then pass the whole text as the prompt to
|
|
4
|
+
`npx genex image "<filled prompt>" --size 2560x1440 --quality high`.
|
|
5
|
+
ONE concept image — no candidate variants unless the player asks for them.
|
|
5
6
|
This image IS the game concept — the user's style checkpoint and the anchor
|
|
6
7
|
for all later art — so the scene half deserves the same care as the HUD half.
|
|
7
8
|
|
|
@@ -26,11 +27,35 @@ Placeholders:
|
|
|
26
27
|
rival truck closing on the left, late-afternoon glare"
|
|
27
28
|
- `[STYLE_BRIEF]` — your full 3–5 sentence style brief with the named 4–5 hue
|
|
28
29
|
palette. Do NOT append the per-sprite cutout sentence here — this is a full
|
|
29
|
-
frame, not a cutout.
|
|
30
|
+
frame, not a cutout. **End the brief with a named register anchor**: "in
|
|
31
|
+
the register of <2–3 real games>" from the table below. Anchors set the
|
|
32
|
+
REGISTER (stroke weight, ornament budget, composure) — never copy their
|
|
33
|
+
assets, and never show their names in-game. Pick 2–3; genres between rows
|
|
34
|
+
blend the neighbors.
|
|
35
|
+
|
|
36
|
+
| Genre register | Anchor games (2–3) |
|
|
37
|
+
|---|---|
|
|
38
|
+
| Gothic / soulslike | Bloodborne, Elden Ring |
|
|
39
|
+
| Clean sci-fi / arena shooter | Destiny 2, Titanfall 2 |
|
|
40
|
+
| Arcade racing / rally | Forza Horizon, vintage Baja rally decals |
|
|
41
|
+
| Cozy / farming / life sim | Stardew Valley, Spiritfarer |
|
|
42
|
+
| Analog survival horror | Resident Evil 7, Signalis |
|
|
43
|
+
| Retro pixel | Shovel Knight |
|
|
44
|
+
| Ornate high fantasy RPG | Diablo IV |
|
|
45
|
+
|
|
46
|
+
- `[N]` — the exact count of elements in `[ELEMENT_LIST]`, spelled out in
|
|
47
|
+
the ONLY-these line. The bans in that line are load-bearing: without them
|
|
48
|
+
the model completes the genre's canonical HUD past your list (invented
|
|
49
|
+
kill feeds, leaderboards, timers, extra slots — measured in 5/7 genres).
|
|
30
50
|
- `[ELEMENT_LIST]` — a bullet list of your 4–7 chosen widgets with one-line
|
|
31
51
|
descriptions. List only asset-backed widgets; pure-geometry elements
|
|
32
52
|
(crosshairs, tick rails, plain shapes) are built in code and stay off the
|
|
33
|
-
list.
|
|
53
|
+
list. **Name each element as the shaped object it is** — "bare glowing
|
|
54
|
+
digits with a pip row", "an etched line silhouette", "stencil digits held
|
|
55
|
+
by two rivet brackets". Never "panel" or "plate" unless a physical plate
|
|
56
|
+
IS the art (a diegetic device, a pinned note). **State exact counts**
|
|
57
|
+
("exactly one tool slot", "exactly three gem sockets") — the model honors
|
|
58
|
+
them.
|
|
34
59
|
|
|
35
60
|
## The template
|
|
36
61
|
|
|
@@ -39,10 +64,12 @@ A screenshot of a complete game HUD for [GENRE_BRIEF]. The HUD is composited ove
|
|
|
39
64
|
|
|
40
65
|
Visual style: [STYLE_BRIEF]
|
|
41
66
|
|
|
42
|
-
The HUD includes these elements,
|
|
67
|
+
The HUD includes ONLY these [N] elements and nothing else — do not add any other UI: no kill feed, no leaderboard, no map, no timer, no chat, no crosshair, no extra slots, no duplicates. Arrange them naturally as a real game would lay them out (you decide the layout — do not force a grid, place each element where it makes the HUD readable and combat-ready):
|
|
43
68
|
|
|
44
69
|
[ELEMENT_LIST]
|
|
45
70
|
|
|
71
|
+
Widget construction rules: every widget is a shaped object with its own silhouette — an ornamented frame or emblem drawn directly over the game scene. NO rectangular backing panels behind bars, digits, or icons; no dark filler boxes; the game scene stays visible right up to each widget's frame edge. All ornament and material character lives ON the frame outline itself. Keep the frames detailed and characterful — confident AAA game UI, not a sterile minimal overlay. Size widgets like a shipped game: the HUD hugs the screen edges and no single widget exceeds about one eighth of the frame width. Every meter channel interior reads visibly darker than both its fill and its surrounding frame.
|
|
72
|
+
|
|
46
73
|
This is a real in-game screenshot. Sharp detail on every UI element. No motion blur on the HUD. The HUD is clear and combat-readable. No watermarks. No external annotations.
|
|
47
74
|
|
|
48
75
|
CRITICAL — flat HUD framing: draw every HUD element flat and head-on, parallel to the screen plane, like a 2D overlay painted directly onto the display (orthographic / screen-space UI). The HUD must NOT be tilted, angled, skewed, rotated in 3D, shown in perspective, or made to recede into depth — no isometric interface, no vanishing point on the panels, no 3D-extruded or floating-at-an-angle widgets, no curved/wrapped screen. ONLY the game scene behind the HUD may show 3D depth and perspective; the HUD layer itself is a flat 2D plane with square-on, axis-aligned edges, so each widget can be cleanly cut out as a flat sprite.
|
|
@@ -53,6 +80,16 @@ not deconstruct cleanly (angled panel edges have no clean silhouette, so
|
|
|
53
80
|
Stage 2 produces sliced, skewed cutouts). If the mockup comes back tilted,
|
|
54
81
|
regenerate it before proceeding; do not try to salvage it downstream.
|
|
55
82
|
|
|
83
|
+
**Never delete the widget-construction paragraph either** — it is what keeps
|
|
84
|
+
the mockup from coming back as generic rectangles: without it, every genre
|
|
85
|
+
grows heavy rectangular backing plates behind its bars and digits, and the
|
|
86
|
+
lane's whole value (shaped, characterful chrome) is lost. The channel-contrast
|
|
87
|
+
sentence in it is deliberate phrasing: channels read "visibly darker than
|
|
88
|
+
both their fill and their frame" — a RELATIVE rule that works on light
|
|
89
|
+
palettes too (an absolute "dark" trough fought cozy/pale briefs). Stage 2's
|
|
90
|
+
EMPTY-state law (dark empty tracks on the sheet) is separate and stays
|
|
91
|
+
absolute.
|
|
92
|
+
|
|
56
93
|
One more Stage-1 rule that pays off at mask time: **meter channels must be
|
|
57
94
|
continuous** — never place a label or ornament in the MIDDLE of a fill
|
|
58
95
|
channel (it splits the mask and the fill into fragments); labels sit above or
|
|
@@ -25,7 +25,11 @@ Fill `[ASSET_LIST]`, then pass the whole text as the prompt to
|
|
|
25
25
|
- **requests variant cells for discrete icon counters** — hearts, ammo
|
|
26
26
|
pips, stars ship as repeated sprites, not masks, so their item asks for
|
|
27
27
|
the states as SEPARATE same-size cells ("the heart icon: one full, one
|
|
28
|
-
half, one empty cell") instead of an annotated pair
|
|
28
|
+
half, one empty cell") instead of an annotated pair;
|
|
29
|
+
- **asks for extra whitespace between meters that were STACKED in the
|
|
30
|
+
mockup** ("place the health-bar cells and the stamina-bar cells in
|
|
31
|
+
separate rows with generous spacing") — adjacent meters otherwise cluster
|
|
32
|
+
into one crop and the extraction tools refuse the pair.
|
|
29
33
|
|
|
30
34
|
## The template
|
|
31
35
|
|
|
@@ -37,7 +41,7 @@ Lay these assets on a pure flat white #ffffff background, separated by at least
|
|
|
37
41
|
[ASSET_LIST]
|
|
38
42
|
|
|
39
43
|
If an asset is a generated progress/bar/meter frame, output TWO CELLS immediately beside each other:
|
|
40
|
-
1. LEFT CELL — the clean production asset the game will use. Preserve exact style, baked_static labels, frame metal, bevels, dividers, scratches, proportions, and texture. Remove runtime dynamic fill and values. Do not paint technical colors on this clean cell.
|
|
44
|
+
1. LEFT CELL — the clean production asset the game will use. Preserve exact style, baked_static labels, frame metal, bevels, dividers, scratches, proportions, and texture. Remove runtime dynamic fill and values. Every meter/bar cell shows the meter EMPTY: the channel interior is painted as the meter's dark empty track in the art's own style — recessed, unlit, like a drained lamp-oil groove or a powered-down light strip. NEVER white, NEVER a filled bar, NEVER the sheet background color inside a frame. Do not paint technical colors on this clean cell.
|
|
41
45
|
2. RIGHT CELL — an annotated duplicate of the same production asset. It must be the same asset, same scale, same canvas bounds, same position, and same outer shape as the left cell. The only difference: paint runtime-fill zones with pure green key color #00ff00. Green marks only the places where runtime bar/progress fill should appear. Paint the green as a FLAT, UNIFORM, fully-saturated #00ff00 fill — no shading, no gradient, no inner shadow, no vignette, NO DARKENING TOWARD THE EDGES, no lighting, no highlights, no texture; constant color edge-to-edge with a HARD, CRISP boundary against the frame. The green is a chroma-key, not a lit surface — any edge shading makes the extracted alpha mask ragged. For segmented meters, paint each segment slot as a separate green shape; do not merge slots into one continuous strip and do not paint half-segments. Never place a label or ornament in the middle of a fill channel — labels belong above/beside the channel or on the frame's end caps.
|
|
42
46
|
|
|
43
47
|
Do NOT create a separate black-background mask cell. Do NOT create a standalone simplified silhouette. The right cell is a registration-safe annotation map; local tooling derives the alpha mask from its green pixels and uses the left cell as the frame.
|
|
@@ -55,7 +59,7 @@ KEEP these baked into the asset — they are part of the panel's IDENTITY and ne
|
|
|
55
59
|
|
|
56
60
|
REMOVE runtime-owned content:
|
|
57
61
|
- Current numeric values (the "1247" coins, the "47" ammo count)
|
|
58
|
-
- Current bar fill levels (the colored fill INSIDE a bar — runtime code
|
|
62
|
+
- Current bar fill levels (the colored fill INSIDE a bar — runtime code paints the fill; the emptied channel shows the meter's own dark empty track, never white, never the sheet background)
|
|
59
63
|
- Current item icons inside slots (the sword, potion — runtime renders the equipped item)
|
|
60
64
|
- Current map content / radar blips (the game paints these at runtime)
|
|
61
65
|
- Any editable or localizable label the design does not fuse into the frame, even if it does not change frame-to-frame
|
|
@@ -141,6 +141,32 @@ use the quad fallback or a hit-spark VFX instead. Impact marks are a first-class
|
|
|
141
141
|
generated surface for any weapon/collision game — inventory them up front with
|
|
142
142
|
the rest of your art, don't discover the bare walls at the end.
|
|
143
143
|
|
|
144
|
+
## Real-translucency glass panels — `--glass`
|
|
145
|
+
|
|
146
|
+
A sprite cut from an unknown background can never carry semi-transparency —
|
|
147
|
+
but a panel generated on a CONTROLLED backdrop can. `--glass` appends a
|
|
148
|
+
flat-magenta key-screen suffix to your prompt, then (after generation) solves
|
|
149
|
+
the per-pixel contamination locally into REAL fractional alpha and writes
|
|
150
|
+
ready RGBA files (`glass-1.png`, one per candidate, into `--out-dir`,
|
|
151
|
+
default `.`) plus the key metrics (key color, strength, flatness):
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
npx genex image "frosted translucent dark glass panel, about 40 percent opacity, thin luminous cyan frame" --glass --size 1280x832 --quality high
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
- **Steer the translucency with words**: "frosted translucent … about 40
|
|
158
|
+
percent opacity" → real see-through glass; "dark smoked glass" → near-
|
|
159
|
+
opaque tint. The suffix handles the backdrop; your prompt owns the glass.
|
|
160
|
+
- **Wire the PNG like any sprite** — its alpha IS the glass. No CSS opacity
|
|
161
|
+
on top, no plate underneath.
|
|
162
|
+
- **Not for magenta/pink-hued art**: magenta in the SUBJECT keys as
|
|
163
|
+
translucency. Panels, frames, HUD plates — yes; a pink neon sign — no.
|
|
164
|
+
- A candidate whose backdrop came back shaded is REJECTED with a retryable
|
|
165
|
+
message (rare — regenerate). `--glass` is generation-only: it conflicts
|
|
166
|
+
with `--edit`/`--clean`/`--upscale`/`--transparent`/`--remove-bg`/`--no-wait`.
|
|
167
|
+
- Glass files are LOCAL outputs (like HUD sprites) — they ship with the
|
|
168
|
+
build; commit them under `public/assets/`.
|
|
169
|
+
|
|
144
170
|
## Multiplayer
|
|
145
171
|
|
|
146
172
|
The asset URL is public, permanent, and CORS-open, so it is safe to broadcast the
|
|
@@ -181,10 +207,22 @@ See `$genex-threejs-multiplayer` for the `shared` channel rules and the room API
|
|
|
181
207
|
- `--quality <low|medium|high>` — quality preset; higher costs more and takes longer.
|
|
182
208
|
- `--size <WxH>` — exact pixel size (multiples of 16, each side ≤ 3840, aspect ≤ 3:1).
|
|
183
209
|
- `--edit <url>` — edit THAT generated image with the prompt (image-to-image).
|
|
210
|
+
- `--inpaint <mask.png|url>` — with `--edit`: a region mask (local PNG or
|
|
211
|
+
asset URL; TRANSPARENT hole = the zone to change). It targets WHERE the
|
|
212
|
+
edit lands — the other regions keep their designs — but the WHOLE image
|
|
213
|
+
still re-renders and alpha is destroyed either way: after any masked edit,
|
|
214
|
+
re-run `--clean`/re-extraction downstream. A targeting scope, not a pixel
|
|
215
|
+
freeze.
|
|
184
216
|
- `--clean <url>` — ML background removal of THAT image only (prompt recorded, unused).
|
|
217
|
+
- `--upscale <url>` — 2x utility upscale of THAT image (prompt recorded,
|
|
218
|
+
unused; ~2-credit class). Use before printing/large billboards, not by
|
|
219
|
+
default.
|
|
185
220
|
- `--remove-bg` — chain ML background removal after the generation/edit.
|
|
186
|
-
- `--bg-mode <sprite|glyph|sheet>` — background-removal model (`glyph`
|
|
187
|
-
digits/closed shapes; `--clean` defaults to `sheet`
|
|
221
|
+
- `--bg-mode <sprite|glyph|sheet|matte>` — background-removal model (`glyph`
|
|
222
|
+
for digits/closed shapes; `--clean` defaults to `sheet`; `matte` = BiRefNet
|
|
223
|
+
SOFT alpha for hair/glow/smoke edges the binary cutters butcher).
|
|
224
|
+
- `--glass` — the magenta-key real-translucency lane (section above);
|
|
225
|
+
writes local RGBA files into `--out-dir` (default `.`).
|
|
188
226
|
- `--no-wait` — enqueue and return immediately, without the URL. Fire-and-forget
|
|
189
227
|
only: re-running the command creates (and bills) a NEW image.
|
|
190
228
|
- `--api-url <url>` — override the API base (local dev).
|
|
@@ -81,7 +81,10 @@ reason is the failure mode this section exists to kill:**
|
|
|
81
81
|
(cinematic, the example below) / CSS plate (styled FROM the brief —
|
|
82
82
|
gradients, borders, chamfers per the game-ui corner rules; default-gray
|
|
83
83
|
plates are a defect) / sprite chrome (from the HUD sheet or a dedicated
|
|
84
|
-
generation — Tier 2b, when the brief is ornate)
|
|
84
|
+
generation — Tier 2b, when the brief is ornate) / real glass
|
|
85
|
+
(`npx genex image "<frosted panel>" --glass` — menus love frosted panels,
|
|
86
|
+
and the solved RGBA carries TRUE translucency over the moving backdrop;
|
|
87
|
+
`$genex-ai-image` documents the lane). The per-genre lean lives
|
|
85
88
|
in the style capsules (`$genex-threejs-game-ui`'s
|
|
86
89
|
references/style-capsules.md) — a lean, not a rule.
|
|
87
90
|
|
|
@@ -136,7 +139,7 @@ cycle. Two stacked `<video>` elements with the same src crossfade at the
|
|
|
136
139
|
cycle end; any seam disappears deterministically, no regeneration lottery.
|
|
137
140
|
|
|
138
141
|
**Phone tiers get the poster, not the videos** (`$genex-threejs-adaptive-quality`):
|
|
139
|
-
two preloading
|
|
142
|
+
two preloading HD decoders while the 3D scene boots is a spike at exactly the
|
|
140
143
|
moment phones get killed for memory. On a phone tier, show the key-art poster
|
|
141
144
|
image (a captured frame of the clip works) and skip `seamlessLoop` entirely —
|
|
142
145
|
or defer ONE non-preloading video until after the first gameplay frame:
|
|
@@ -171,19 +174,40 @@ export function seamlessLoop(holder: HTMLElement, url: string, fade = 0.6): void
|
|
|
171
174
|
|
|
172
175
|
Pause both videos when the menu phase hides (they're decode work), and
|
|
173
176
|
resume the front one when it returns. Watch ONE full cycle in the browser
|
|
174
|
-
before calling the menu done — that's the seam check
|
|
177
|
+
before calling the menu done — that's the seam check, and once the video is
|
|
178
|
+
wired it is the menu's capture in the milestone smoke pass: one full loop
|
|
179
|
+
cycle watched AS RENDERED. A metadata probe (ffprobe) can't see a seam, a
|
|
180
|
+
panel covering the video, or a video that never plays — only watching can.
|
|
175
181
|
|
|
176
182
|
**Work async — the menu must never block the game.** The still is
|
|
177
|
-
`--edit`-anchored to the concept mockup, so it's style-dependent:
|
|
178
|
-
the moment the
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
183
|
+
`--edit`-anchored to the concept mockup, so it's style-dependent: enqueue it
|
|
184
|
+
`--no-wait` **the moment the concept mockup LANDS** — it rides the same
|
|
185
|
+
immediate chain as the HUD Stage-2 sheet and the logotype; the user's
|
|
186
|
+
keep/change answer never gates it (a later "change" just re-edits it against
|
|
187
|
+
the new frame, image-priced). **Only the VIDEO — the expensive item — waits,
|
|
188
|
+
and its trigger is an event, never a clock: fire it at the FIRST of (a) the
|
|
189
|
+
user's yes to the concept, (b) the next `genex preview` push after the still
|
|
190
|
+
has landed (a shipped milestone with the user silent = the pick stands), or
|
|
191
|
+
(c) style art being the only work left. Never fire it while a user objection
|
|
192
|
+
is open** ("change the colors" blocks it until the loop resolves). Ship the
|
|
193
|
+
CSS menu (buttons + title over the frame IMAGE as a static backdrop) and
|
|
194
|
+
swap the `<video>` in when `genex wait` prints the URL. The frame image doubles as the
|
|
182
195
|
**loading screen background** — it exists minutes before the video does (see
|
|
183
196
|
`$genex-threejs-game-ui`'s loader spec). Both assets live in Genex storage
|
|
184
197
|
(R2) — permanent, public, CORS-open; you load them straight from the printed
|
|
185
198
|
URLs, nothing is downloaded or committed.
|
|
186
199
|
|
|
200
|
+
**When the generated art lands, the upgrade is a RE-COMPOSITION — not a
|
|
201
|
+
backdrop swap.** DELETE the placeholder panel/card the moment the still or
|
|
202
|
+
video goes in: the still was generated with negative space precisely so the
|
|
203
|
+
buttons and logo sit DIRECTLY on the key art. A placeholder card left
|
|
204
|
+
floating over the finished video is the single most common bad menu — a
|
|
205
|
+
near-opaque panel (plus its darkening layers) hides the art you just paid
|
|
206
|
+
for, and the menu reads as the plain CSS draft it started as. Allowed over
|
|
207
|
+
the art: a thin, low-opacity scrim strictly behind the button rail for
|
|
208
|
+
legibility, and at most ONE subtle full-screen grade layer. NEVER a
|
|
209
|
+
card/panel covering the art.
|
|
210
|
+
|
|
187
211
|
**Two failed video attempts = ship the still. Hard stop.** Video is the one
|
|
188
212
|
generation that fails server-side with real frequency (render timeouts), and
|
|
189
213
|
every attempt costs minutes of waiting. One retry is fair — shorten the clip
|
|
@@ -350,7 +374,11 @@ not):
|
|
|
350
374
|
`npx genex image "the word 'EMBERFALL' as an ornate engraved game logo, <style brief>" --transparent`
|
|
351
375
|
— the wordmark alone on a transparent background, in the brief's display
|
|
352
376
|
register, no extra text or scenery. Clean with `--bg-mode glyph` if letter
|
|
353
|
-
counters get eaten, trim with `npx genex ui trim`.
|
|
377
|
+
counters get eaten, trim with `npx genex ui trim`. Then VERIFY it is
|
|
378
|
+
actually transparent — view the trimmed PNG over a bright test background;
|
|
379
|
+
background removal sometimes leaves an opaque disc or plate behind the
|
|
380
|
+
mark, and that plate ships as a hole punched in your key art. If any
|
|
381
|
+
background remains, re-run the clean. Short names (one or two
|
|
354
382
|
words) come out best. Wire it as the menu title AND the loader mark; the
|
|
355
383
|
DOM keeps an accessible text fallback (`aria-label` or visually-hidden
|
|
356
384
|
text).
|
|
@@ -370,14 +398,12 @@ not):
|
|
|
370
398
|
re-anchored the look) re-opens this rule once — re-edit the still
|
|
371
399
|
(`--edit` against the new concept mockup) and re-run the video from the
|
|
372
400
|
new still. Agent-initiated polish never does.
|
|
373
|
-
- **The menu
|
|
374
|
-
frame-conditioned
|
|
375
|
-
1080p
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
re-triggering the 422 and losing the video entirely. (Plain text-to-video,
|
|
380
|
-
without `--frame`, still defaults to 1080p.)
|
|
401
|
+
- **The menu video renders 1080p by default — leave it alone.** Every video
|
|
402
|
+
path, the frame-conditioned (`--frame`) menu route included, defaults to
|
|
403
|
+
1080p: the menu clip is full-screen key art, and 720p stretched across a
|
|
404
|
+
desktop reads soft. Don't pass a resolution flag at all; `--resolution 720p`
|
|
405
|
+
exists only as a deliberate cost opt-down for clips that are genuinely
|
|
406
|
+
incidental — never the main menu.
|
|
381
407
|
- **Pause/victory/defeat variants reuse the same video — as GRADES.** Same
|
|
382
408
|
`<video>` element or URL, different emotion via CSS `filter` on the
|
|
383
409
|
background: pause = a plain dark overlay (`rgba(0,0,0,0.55)`); defeat =
|
|
@@ -407,11 +433,10 @@ not):
|
|
|
407
433
|
genuine state change; expect a loop seam.
|
|
408
434
|
- `--duration <sec>` (video) — 4, 6, or 8 for frame-conditioned clips;
|
|
409
435
|
default 8.
|
|
410
|
-
- `--resolution <720p|1080p>` (video) —
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
(
|
|
414
|
-
resolution parameter).
|
|
436
|
+
- `--resolution <720p|1080p>` (video) — every path defaults to **1080p**, the
|
|
437
|
+
`--frame` menu route included. `720p` is the deliberate cost opt-down
|
|
438
|
+
(~half the credits) for incidental clips — not for the menu. Loop clips
|
|
439
|
+
(`--loop`) ignore it (that model has no resolution parameter).
|
|
415
440
|
- `--aspect 16:9 --quality high` (image) — the right settings for a menu frame.
|
|
416
441
|
- `--no-wait` — enqueue and return immediately with the generation id; pick
|
|
417
442
|
the result up later with `npx genex wait <id>` (safe to re-run — it attaches
|
|
@@ -14,6 +14,14 @@ Turn a text prompt into a real, game-ready **GLB** and drop it into the project.
|
|
|
14
14
|
- **Use `$genex-threejs-procedural-geometry`** for parametric/abstract shapes,
|
|
15
15
|
terrain, or anything you want to generate in code (infinite variations, no files).
|
|
16
16
|
|
|
17
|
+
**The output is a STATIC, unrigged mesh — no skeleton, no animation clips.**
|
|
18
|
+
A "wolf" or "guard" from this command can be posed and moved as one object,
|
|
19
|
+
but its limbs cannot animate. Anything that must walk, attack, or die on
|
|
20
|
+
screen routes to the creature lane instead: `npx genex creature` for
|
|
21
|
+
biped-shaped bodies (real rig + library clips), or this command plus the
|
|
22
|
+
procedural-motion recipes for everything else — `$genex-threejs-creatures`
|
|
23
|
+
owns that split. The player's own character is `$genex-ai-character`.
|
|
24
|
+
|
|
17
25
|
## Run
|
|
18
26
|
|
|
19
27
|
```bash
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: genex-ai-music
|
|
3
|
+
description: Generate a real instrumental background-music track (mp3) from a text prompt with `npx genex music`, then loop it quietly under the game in Three.js. Use for the one looping gameplay track every game with generated audio should have (reused on the menu at lower volume), plus optional boss or menu-specific tracks — always instrumental, always behind Music/SFX volume sliders in settings.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Genex AI · Music
|
|
7
|
+
|
|
8
|
+
Turn a prompt into a real **mp3** instrumental track and loop it under the game.
|
|
9
|
+
One track transforms how finished a game feels — a silent game with polished art
|
|
10
|
+
still reads as a tech demo.
|
|
11
|
+
|
|
12
|
+
## When to use this vs. sfx
|
|
13
|
+
|
|
14
|
+
- **Use `npx genex music`** for the continuous bed: the gameplay loop, a boss
|
|
15
|
+
theme, a menu theme. Tracks are instrumental by design (the API enforces it —
|
|
16
|
+
vocals under gameplay read as karaoke).
|
|
17
|
+
- **Use `$genex-ai-sfx`** for event sounds — impacts, pickups, UI ticks. The
|
|
18
|
+
0.5–22 s sfx lane cannot produce a music bed; don't try.
|
|
19
|
+
|
|
20
|
+
**The default plan is ONE track:** a ~90 s loopable gameplay track, reused on
|
|
21
|
+
the menu (same URL, lower volume). Propose extra tracks (boss/menu-specific) as
|
|
22
|
+
their own Assets-table rows only when the game's shape earns them.
|
|
23
|
+
|
|
24
|
+
## Run
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx genex music "<prompt>" --no-wait
|
|
28
|
+
npx genex music "dark orchestral hunt, low strings and taiko, steady menace, seamless loop, consistent energy, no intro, no outro" --duration 120 --no-wait
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`--duration <sec>` (10–300) sets the length; the default **90 s** is the sweet
|
|
32
|
+
spot for a loop. Music takes a minute-plus — enqueue with `--no-wait` alongside
|
|
33
|
+
your other generations and pick it up with `npx genex wait <id>`. Prints:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
https://assets.genex.technology/generations/<id>/audio-music
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The mp3 lives in Genex storage (R2) and loads straight from that URL — you don't
|
|
40
|
+
download it and nothing is committed to your repo. The URL is permanent (local
|
|
41
|
+
dev, published game, and remixes alike).
|
|
42
|
+
|
|
43
|
+
## Prompt recipe for loopable game music
|
|
44
|
+
|
|
45
|
+
Mood + instrumentation + energy + loop wording:
|
|
46
|
+
|
|
47
|
+
- Name the game's emotional register and 2–3 instruments ("brooding synthwave,
|
|
48
|
+
analog pads and arpeggio", "cozy acoustic folk, fingerpicked guitar and soft
|
|
49
|
+
strings").
|
|
50
|
+
- Always end with: **"seamless loop, consistent energy, no intro, no outro"** —
|
|
51
|
+
there is no API loop flag; consistent energy at both ends is what makes
|
|
52
|
+
`setLoop(true)` inaudible. A track with a big intro pops every cycle.
|
|
53
|
+
- Don't ask for vocals — the lane forces instrumental regardless.
|
|
54
|
+
|
|
55
|
+
## Wire it in Three.js
|
|
56
|
+
|
|
57
|
+
Music is **non-positional** (`THREE.Audio`, not `PositionalAudio`), looped,
|
|
58
|
+
and QUIET — the default volume is **0.30**: it sits under the sfx, never over
|
|
59
|
+
them. Browsers block autoplay, so start it on the first user gesture:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import * as THREE from "three";
|
|
63
|
+
|
|
64
|
+
const listener = new THREE.AudioListener();
|
|
65
|
+
camera.add(listener); // ONE listener serves music and every sfx
|
|
66
|
+
|
|
67
|
+
// the URL `npx genex music` printed (R2 sends CORS headers, cross-origin works):
|
|
68
|
+
const MUSIC_URL = "https://assets.genex.technology/generations/<id>/audio-music";
|
|
69
|
+
const music = new THREE.Audio(listener);
|
|
70
|
+
new THREE.AudioLoader().loadAsync(MUSIC_URL).then((buffer) => {
|
|
71
|
+
music.setBuffer(buffer);
|
|
72
|
+
music.setLoop(true);
|
|
73
|
+
music.setVolume(0.30); // the default — under the sfx, never over them
|
|
74
|
+
// autoplay policy: start on the first gesture (the menu's PLAY click is ideal)
|
|
75
|
+
const start = (): void => {
|
|
76
|
+
if (!music.isPlaying) music.play();
|
|
77
|
+
};
|
|
78
|
+
window.addEventListener("click", start, { once: true });
|
|
79
|
+
window.addEventListener("keydown", start, { once: true });
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Suspend when the tab hides (decode work + politeness), resume on return:
|
|
83
|
+
document.addEventListener("visibilitychange", () => {
|
|
84
|
+
const ctx = listener.context;
|
|
85
|
+
if (document.hidden) void ctx.suspend();
|
|
86
|
+
else void ctx.resume();
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Menu reuse:** the same `music` object at lower volume (`setVolume(0.18)`)
|
|
91
|
+
during the menu phase, restored to the setting's value on PLAY — zero extra
|
|
92
|
+
generations. If the loop point is audible (the track came back with an
|
|
93
|
+
intro/outro despite the prompt), crossfade the tail into the head with a second
|
|
94
|
+
`THREE.Audio` on the same buffer rather than regenerating.
|
|
95
|
+
|
|
96
|
+
## Volume sliders are NOT optional
|
|
97
|
+
|
|
98
|
+
A game with generated audio and no volume control is a failure mode. The
|
|
99
|
+
settings screen gets **two sliders — Music and SFX** (music default 0.30, sfx
|
|
100
|
+
~0.7), persisted (localStorage or the save slot) and applied live:
|
|
101
|
+
`music.setVolume(v)` for the music bed; keep every sfx's volume routed through
|
|
102
|
+
one shared multiplier. `$genex-threejs-game-ui` carries this as a hard settings
|
|
103
|
+
rule — wire the sliders in the same milestone as the track.
|
|
104
|
+
|
|
105
|
+
## Publish checklist
|
|
106
|
+
|
|
107
|
+
- Load it from the **URL** the command printed — absolute and permanent, so it
|
|
108
|
+
resolves the same in local dev, the published game, and remixes. Nothing to
|
|
109
|
+
commit.
|
|
110
|
+
- The track must be audible in the shipped game AND adjustable in settings —
|
|
111
|
+
an unwired paid track is flagged at preview/publish (the wiring audit).
|
|
112
|
+
|
|
113
|
+
## Options
|
|
114
|
+
|
|
115
|
+
- `--duration <sec>` — track length 10–300; default 90 (the loop sweet spot).
|
|
116
|
+
Longer costs more; a 90–120 s loop outlasts most sessions.
|
|
117
|
+
- `--no-wait` — enqueue and return immediately with the generation id; pick it
|
|
118
|
+
up later with `npx genex wait <id>` (safe to re-run — it attaches to the SAME
|
|
119
|
+
generation). The default for music: build while it renders.
|
|
120
|
+
- `--api-url <url>` — override the API base (local dev).
|
|
121
|
+
|
|
122
|
+
## Troubleshooting
|
|
123
|
+
|
|
124
|
+
- **"Not authorized"** — run `npx genex init` first (in the project — it resolves this project's own CLI) (it writes your `GENEX_TOKEN`).
|
|
125
|
+
- **"Out of credits" (`insufficient_credits`)** — the account has no credits left
|
|
126
|
+
for this music generation. Tell the user the facts the CLI printed: their
|
|
127
|
+
balance, this generation's cost, and when their credits refill. Then continue
|
|
128
|
+
the build without a music bed (the game must work silent anyway) and mark the
|
|
129
|
+
spot with `// TODO(genex): regenerate when credits refill` so the real track
|
|
130
|
+
is one command away later. Do not stop the session over this.
|
|
131
|
+
- **"Email not verified" (`email_verification_required`)** — generation credits
|
|
132
|
+
unlock after the account's email is verified. Give the user the verify link
|
|
133
|
+
the CLI printed, wait for them to confirm, then re-run the command.
|
|
134
|
+
- **No sound** — the `AudioContext` is suspended until a user gesture; the
|
|
135
|
+
first `music.play()` must come from a click/keydown. Confirm the camera has
|
|
136
|
+
an `AudioListener`.
|
|
137
|
+
- **The loop "pops" every cycle** — the track has an intro/outro (the prompt
|
|
138
|
+
missed the loop wording). One regeneration with "seamless loop, consistent
|
|
139
|
+
energy, no intro, no outro" is fair; after that, crossfade tail-into-head
|
|
140
|
+
with a second `THREE.Audio` on the same buffer instead of re-rolling.
|
|
141
|
+
- **Music drowns the game** — 0.30 is the ceiling for a bed, not the floor;
|
|
142
|
+
drop it further under dialogue-heavy or ambience-led scenes.
|
|
@@ -10,13 +10,26 @@ also lights it (image-based lighting).
|
|
|
10
10
|
|
|
11
11
|
## When to use this vs. a procedural sky
|
|
12
12
|
|
|
13
|
-
- **Use `npx genex skybox`** for a specific,
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
- **Use `npx genex skybox`** for a specific, describable ENVIRONMENT — "golden
|
|
14
|
+
hour over misty mountains", "rolling thunderstorm, towering cumulonimbus",
|
|
15
|
+
"alien purple nebula", "hazy dusk sky over a distant sea horizon". You get a
|
|
16
|
+
real image.
|
|
16
17
|
- **Use `$genex-threejs-atmosphere-aerial-perspective`** (or
|
|
17
18
|
`$genex-threejs-volumetric-clouds`) for a fully procedural, animated,
|
|
18
19
|
time-of-day sky generated in shaders.
|
|
19
20
|
|
|
21
|
+
**A skybox is environment only — never content.** Buildings, trees, ruins,
|
|
22
|
+
towers, or any object painted into the sky render at infinite distance: they
|
|
23
|
+
never get closer as the player moves, they sit at the wrong parallax against
|
|
24
|
+
the real 3D world, and they read as broken the moment the camera strafes.
|
|
25
|
+
Structures belong in the scene as geometry (`npx genex model`); the sky
|
|
26
|
+
carries atmosphere — light, weather, clouds, haze, stars. The CLI enforces
|
|
27
|
+
this: every skybox prompt gets an environment-only suffix appended (you'll
|
|
28
|
+
see `↳ environment-only guard applied` and the full final prompt is stored
|
|
29
|
+
with the generation). If you genuinely need content baked into the sky —
|
|
30
|
+
e.g. a space station panorama for a scene with no world geometry — pass
|
|
31
|
+
`--raw` to send your prompt exactly as written.
|
|
32
|
+
|
|
20
33
|
## Run
|
|
21
34
|
|
|
22
35
|
```bash
|
|
@@ -81,8 +94,11 @@ scene.background = texture; // keep the raw texture for the visible sky
|
|
|
81
94
|
|
|
82
95
|
## Options
|
|
83
96
|
|
|
84
|
-
- `--
|
|
85
|
-
|
|
97
|
+
- `--raw` — send the prompt exactly as written, skipping the appended
|
|
98
|
+
environment-only guard (for the rare sky that must carry content).
|
|
99
|
+
- `--no-wait` — enqueue and return immediately with the generation id; pick
|
|
100
|
+
the result up later with `npx genex wait <id>` (safe to re-run — it attaches
|
|
101
|
+
to the SAME generation).
|
|
86
102
|
- `--api-url <url>` — override the API base (local dev).
|
|
87
103
|
|
|
88
104
|
## Troubleshooting
|
|
@@ -37,11 +37,13 @@ The clip lives in Genex storage (R2) and loads straight from that URL — you do
|
|
|
37
37
|
download it and nothing is committed to your repo. The URL is permanent (local dev,
|
|
38
38
|
published game, and remixes alike).
|
|
39
39
|
|
|
40
|
-
> **Cost & length:** the default is a **5-second,
|
|
41
|
-
>
|
|
42
|
-
> genuinely needs to be longer (a cutscene)
|
|
43
|
-
>
|
|
44
|
-
>
|
|
40
|
+
> **Cost & length:** the default is a **5-second, 1080p** clip — the right default
|
|
41
|
+
> for anything the player looks at directly. Only pass `--duration` when the content
|
|
42
|
+
> genuinely needs to be longer (a cutscene), and `--resolution 720p` only when the
|
|
43
|
+
> clip is genuinely incidental (a small in-world screen seen from a distance): it
|
|
44
|
+
> halves the cost, but 720p stretched across the whole screen reads soft. mp4 has
|
|
45
|
+
> **no alpha channel**, so a video is always a full rectangle (there are no
|
|
46
|
+
> transparent video decals).
|
|
45
47
|
|
|
46
48
|
## Play it in Three.js
|
|
47
49
|
|
|
@@ -80,8 +82,9 @@ window.addEventListener("keydown", () => {
|
|
|
80
82
|
One `VideoTexture` can feed **many** surfaces — a bank of monitors, N sprays. Cost is
|
|
81
83
|
per distinct `<video>` element (media decode + one GPU upload per frame), **not** per
|
|
82
84
|
surface, so sharing one element for every screen is nearly free (all play in sync).
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
Pause the element (`video.pause()`) when no video surface is visible; on phones,
|
|
86
|
+
prefer the clip's source still as a poster and start the video only where it plays
|
|
87
|
+
smoothly.
|
|
85
88
|
|
|
86
89
|
## Video decals
|
|
87
90
|
|
|
@@ -132,6 +135,9 @@ See `$genex-threejs-multiplayer` for the `shared` channel rules and the room API
|
|
|
132
135
|
- `--loop` — a seamless loop (for screens, ambient backdrops, video decals).
|
|
133
136
|
- `--duration <sec>` — clip length 1–15; default 5. Only raise it when the content
|
|
134
137
|
genuinely needs more — longer clips cost more and take longer.
|
|
138
|
+
- `--resolution 720p|1080p` — output resolution (default **1080p**). `--resolution
|
|
139
|
+
720p` halves the cost — use it only when quality genuinely doesn't matter (a small
|
|
140
|
+
far-away in-world screen). `--loop` clips ignore it (model default).
|
|
135
141
|
- `--frame <url>` — one generated image as BOTH first and last frame — the
|
|
136
142
|
seamless-loop mode (motion must return to its start).
|
|
137
143
|
- `--first-frame <url>` / `--last-frame <url>` — two-frame motion between two
|