@genex-ai/cli-demo 0.68.0-dev.174 → 0.69.0-dev.175
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/package.json +1 -1
- package/templates/skills/genex-threejs-camera-direction/SKILL.md +48 -8
- package/templates/skills/genex-threejs-camera-direction/references/camera-rigs.md +62 -0
- package/templates/skills/genex-threejs-game-feel/SKILL.md +4 -1
- package/templates/skills/genex-threejs-game-ui/SKILL.md +34 -2
- package/templates/skills/genex-threejs-skill-router/SKILL.md +12 -4
- package/templates/skills/genex-threejs-skill-router/references/routing-map.md +5 -2
- package/templates/skills/genex-threejs-touch-controls/SKILL.md +4 -0
- package/templates/skills/genex-threejs-visual-validation/SKILL.md +29 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genex-ai/cli-demo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.69.0-dev.175",
|
|
4
4
|
"description": "Set up your project's agent workspace (.claude/.codex/.cursor in the game folder), authorize, create a game project, generate AI assets, and publish (genex CLI).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -35,9 +35,12 @@ rules, floating-origin shot, pointer controls, and implementation limits.
|
|
|
35
35
|
|
|
36
36
|
## Aiming and pointer lock
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
The rule is binary: during play, **the cursor is either a gameplay tool or it is
|
|
39
|
+
locked away**. An OS arrow parked over the action in a game that never uses it is
|
|
40
|
+
a shipped defect, not a default. On the bundled `FollowCamera`, pointer-lock aim
|
|
41
|
+
is ON by default on desktop — a click locks the pointer and raw mouse movement
|
|
42
|
+
drives the view — so mostly you decide whether to turn it OFF. Name the bucket in
|
|
43
|
+
the build plan:
|
|
41
44
|
|
|
42
45
|
- **MANDATORY** — first-person of any kind (FPS, walking sim, horror) and any
|
|
43
46
|
mouse-aimed action (third-person shooter, turret/range). Lock is on by default;
|
|
@@ -47,11 +50,16 @@ it on — you decide whether to turn it OFF. Name the bucket in the build plan:
|
|
|
47
50
|
`genex controller character` game). On by default; leave it on. Opt out with
|
|
48
51
|
`pointerLockAim: false` only for a stated reason (a cursor-heavy UI at the core
|
|
49
52
|
of play).
|
|
50
|
-
- **
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
- **Keyboard-driven games lock too** — a racer, platformer, or runner that never
|
|
54
|
+
reads the mouse still locks the pointer on the play/Start click: the cursor is
|
|
55
|
+
not a tool there, so lock it away (hidden cursor, no stray clicks, Esc = pause
|
|
56
|
+
as usual). Bundled-controller games get this for free; a hand-rolled game uses
|
|
57
|
+
the minimal lock recipe in `$genex-threejs-game-ui` (~6 lines).
|
|
58
|
+
- **NEVER** — cursor-core games where the pointer IS the gameplay tool (top-down
|
|
59
|
+
click-to-move, tower defense, builders, card/board/puzzle) and spectator/orbit
|
|
60
|
+
showcases. These **must pass `pointerLockAim: false`** — otherwise the bundled
|
|
61
|
+
camera grabs the cursor on the first click. (Touch needs nothing: pointer lock
|
|
62
|
+
doesn't exist there and the mode no-ops on coarse pointers.)
|
|
55
63
|
|
|
56
64
|
**Mechanism — games on the bundled controller (most games):** do NOT hand-roll
|
|
57
65
|
lock handling. Aim is already enabled; the kit ships a ready-made cue overlay —
|
|
@@ -113,6 +121,36 @@ grants the permission.
|
|
|
113
121
|
(trackpad "natural scrolling" only flips the wheel). If look feels inverted it's a
|
|
114
122
|
sign bug in the rig, not a device quirk — fix the sign, don't sniff the trackpad.
|
|
115
123
|
|
|
124
|
+
## The screen-direction contract
|
|
125
|
+
|
|
126
|
+
Every input axis has one correct on-screen direction, for every rig, bundled or
|
|
127
|
+
hand-rolled. These four invariants are testable and non-negotiable:
|
|
128
|
+
|
|
129
|
+
1. Mouse/touchpad RIGHT turns the view right; mouse UP looks up (down only behind
|
|
130
|
+
an explicit invert option the player chose).
|
|
131
|
+
2. `KeyD`/ArrowRight moves or turns the player toward screen-RIGHT; `KeyA`/
|
|
132
|
+
ArrowLeft toward screen-left. Same for a touch stick's +x.
|
|
133
|
+
3. Drag-pan picks ONE convention — grab-the-world (terrain follows the pointer)
|
|
134
|
+
or move-the-camera — and BOTH axes obey it. One axis each is the
|
|
135
|
+
"diagonals feel twisted" bug.
|
|
136
|
+
4. See the OS-setting note above: inversion is always your sign, never the device.
|
|
137
|
+
|
|
138
|
+
The formula that settles every sign argument: `screenRight = cross(cameraForward, worldUp)`.
|
|
139
|
+
For a Y-up world and forward `(sin yaw, 0, cos yaw)`, screen-right is
|
|
140
|
+
`(-cos yaw, 0, sin yaw)`. **Warning — `(cos yaw, 0, -sin yaw)` is the LEFT
|
|
141
|
+
vector** (that's `cross(worldUp, cameraForward)`), and writing it as "right" is
|
|
142
|
+
the single most-shipped direction bug in generated games: two independent
|
|
143
|
+
projects inverted their A/D exactly this way. Related trap: positive
|
|
144
|
+
`rotation.y` turns a +Z-facing object toward +X, which is screen-LEFT from a
|
|
145
|
+
chase camera behind it — so "positive yaw = turn right" is false in this basis.
|
|
146
|
+
|
|
147
|
+
Never derive signs by intuition — intuition about right-handed frames is wrong
|
|
148
|
+
about half the time and has been wrong in every shipped instance. Copy a
|
|
149
|
+
verified pair (sign AND basis together) from
|
|
150
|
+
[references/camera-rigs.md](references/camera-rigs.md), then confirm with the
|
|
151
|
+
input-direction part of the smoke check: hold D and watch which way the world
|
|
152
|
+
answers.
|
|
153
|
+
|
|
116
154
|
## Non-negotiable rules
|
|
117
155
|
|
|
118
156
|
- Use subject dimensions to derive offsets; do not tune one fixed distance for
|
|
@@ -122,6 +160,8 @@ sign bug in the rig, not a device quirk — fix the sign, don't sniff the trackp
|
|
|
122
160
|
- During an explicit handoff, use one interpolation stage. Do not stack a
|
|
123
161
|
transition blend and a second follow smoother over the same interval.
|
|
124
162
|
- Re-sync yaw/pitch from the camera when pointer lock is acquired.
|
|
163
|
+
- Hand-rolled steering/pan/look math copies a verified basis from the reference
|
|
164
|
+
and passes the input-direction check — signs are never derived by intuition.
|
|
125
165
|
- Update the projection matrix whenever FOV, near, far, or aspect changes.
|
|
126
166
|
- Keep stars or infinite backgrounds camera-relative when large translation
|
|
127
167
|
would create false parallax or precision loss.
|
|
@@ -11,6 +11,7 @@ Use this reference for scale-aware chase, side, orbit, authored-shot, pointer-lo
|
|
|
11
11
|
- Explicit camera handoffs
|
|
12
12
|
- cinematic implementation shot ownership
|
|
13
13
|
- Pointer-look and movement constraints
|
|
14
|
+
- Verified screen-direction bases
|
|
14
15
|
- Floating origin and background handling
|
|
15
16
|
- Projection and lifecycle ownership
|
|
16
17
|
- Failure modes and diagnostics
|
|
@@ -166,6 +167,9 @@ yaw -= mouseDeltaX * 0.0022
|
|
|
166
167
|
pitch -= mouseDeltaY * 0.0018
|
|
167
168
|
```
|
|
168
169
|
|
|
170
|
+
Expected on screen: mouse-right orbits the view right, mouse-up tilts it up —
|
|
171
|
+
verify both axes against the screen-direction contract before retuning the scales.
|
|
172
|
+
|
|
169
173
|
Pitch bounds vary by flight mode. The implementation also enforces camera height above
|
|
170
174
|
the ship:
|
|
171
175
|
|
|
@@ -281,6 +285,9 @@ distance = movementSpeed * dt
|
|
|
281
285
|
|
|
282
286
|
Default speed is `9`, sensitivity `0.0023`.
|
|
283
287
|
|
|
288
|
+
Expected on screen: mouse-right turns the view right, mouse-up looks up — assert
|
|
289
|
+
both axes (yaw-only evidence has let inverted pitch ship).
|
|
290
|
+
|
|
284
291
|
Keys are cleared on:
|
|
285
292
|
|
|
286
293
|
- pointer-lock exit;
|
|
@@ -295,6 +302,61 @@ Scene-specific constraints then run after controls:
|
|
|
295
302
|
|
|
296
303
|
Input control and spatial constraint are separate layers.
|
|
297
304
|
|
|
305
|
+
## Verified screen-direction bases
|
|
306
|
+
|
|
307
|
+
Copy these pairs whole — the sign and the basis are only correct TOGETHER. Each
|
|
308
|
+
was derived from `screenRight = cross(cameraForward, worldUp)` and verified
|
|
309
|
+
against the on-screen result; if you change one half, re-verify with the
|
|
310
|
+
input-direction check instead of reasoning about it.
|
|
311
|
+
|
|
312
|
+
**Chase-cam steering** (vehicle/character heading, camera behind):
|
|
313
|
+
|
|
314
|
+
```text
|
|
315
|
+
heading = (sin yaw, 0, cos yaw) // matches rotation.y for a +Z-front model
|
|
316
|
+
yaw -= steer * rate * dt // steer: D/right = +1, A/left = -1
|
|
317
|
+
position += heading * speed * dt
|
|
318
|
+
camera at position - heading * dist, lookAt(position)
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
Why the minus: the camera looks along `heading`, so screen-right is
|
|
322
|
+
`cross(heading, up) = (-cos yaw, 0, sin yaw)`, while `d(heading)/d(yaw) =
|
|
323
|
+
(cos yaw, 0, -sin yaw)` — exactly screen-LEFT. Increasing yaw always veers the
|
|
324
|
+
nose left on screen, so "D turns right" needs `yaw -=`. (Equivalently
|
|
325
|
+
`yaw += steer` is correct only with heading `(-sin yaw, 0, cos yaw)` — a pair,
|
|
326
|
+
never a lone sign.)
|
|
327
|
+
|
|
328
|
+
**RTS / overhead pan camera** (fixed pitch, yaw-orbiting):
|
|
329
|
+
|
|
330
|
+
```text
|
|
331
|
+
right = (-cos yaw, 0, sin yaw) // pitch-independent screen-right on the ground
|
|
332
|
+
forwardGround = (sin yaw, 0, cos yaw) // into the screen along the ground
|
|
333
|
+
D / ArrowRight: target += right * pan A / ArrowLeft: target -= right * pan
|
|
334
|
+
W / ArrowUp: target += forwardGround * pan S: target -= forwardGround * pan
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Drag-pan, grab-the-world (terrain follows the pointer; both axes, one
|
|
338
|
+
convention — `movementY` is positive DOWNWARD):
|
|
339
|
+
|
|
340
|
+
```text
|
|
341
|
+
target -= right * movementX * k
|
|
342
|
+
target += forwardGround * movementY * k
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Move-the-camera convention = flip BOTH signs, never one. The classic shipped bug
|
|
346
|
+
writes `right = (cos yaw, 0, -sin yaw)` — that is `cross(up, forward)`, the LEFT
|
|
347
|
+
vector — inverting A/D and the horizontal drag while W/S stay correct.
|
|
348
|
+
|
|
349
|
+
**Pointer-look** (locked mouse driving yaw/pitch, Euler order `YXZ`):
|
|
350
|
+
|
|
351
|
+
```text
|
|
352
|
+
yaw -= movementX * sensitivity // mouse-right -> view turns RIGHT
|
|
353
|
+
pitch -= movementY * sensitivity // mouse-up -> view tilts UP
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Expected on screen, both axes, before any tuning: a straight-ahead landmark
|
|
357
|
+
slides LEFT when the mouse moves right (the view pans right) and slides DOWN
|
|
358
|
+
when the mouse moves up (the view tilts up).
|
|
359
|
+
|
|
298
360
|
## Floating origin and background handling
|
|
299
361
|
|
|
300
362
|
The Saturn scene first computes a virtual camera pose, stores its orientation
|
|
@@ -37,7 +37,10 @@ no matter how good it looks.
|
|
|
37
37
|
unlocked drag-to-turn camera feels imprecise no matter how tight the numbers
|
|
38
38
|
are. The bucket rule + the bundled `FollowCamera` aim mode live in
|
|
39
39
|
`$genex-threejs-camera-direction`; on the bundled controller it's ON by default
|
|
40
|
-
(with a ready-made cue), not hand-rolled events.
|
|
40
|
+
(with a ready-made cue), not hand-rolled events. Direction is half of it: a
|
|
41
|
+
movement key or look axis whose on-screen direction contradicts its label is a
|
|
42
|
+
defect, not a tuning issue — the screen-direction contract and verified bases
|
|
43
|
+
are in `$genex-threejs-camera-direction`.
|
|
41
44
|
|
|
42
45
|
## Movement: snappy beats realistic
|
|
43
46
|
|
|
@@ -250,8 +250,15 @@ document.addEventListener("keydown", (e) => {
|
|
|
250
250
|
so ALSO keep the pointer-lock-loss → pause path (`pointerlockchange`: if
|
|
251
251
|
unlocked while `playing`, `setPhase("paused")`). Escape then always pauses; it
|
|
252
252
|
only *also* drops fullscreen on browsers without the lock — unavoidable there.
|
|
253
|
-
- **
|
|
254
|
-
|
|
253
|
+
- **Skip Keyboard Lock + fullscreen only when the cursor stays a tool.**
|
|
254
|
+
Cursor-core / top-down / menu-driven games never capture the pointer — skip
|
|
255
|
+
`enterImmersive` and Keyboard Lock entirely. But ANY game that locks the
|
|
256
|
+
pointer during play — aim games AND keyboard-only racers/platformers/runners
|
|
257
|
+
under the lock-or-tool rule (next section) — keeps the Escape → pause path and
|
|
258
|
+
the `pointerlockchange` fallback (if unlocked while `playing`, pause): without
|
|
259
|
+
it, Esc frees the cursor while the game keeps running. Keyboard-only games may
|
|
260
|
+
still skip Keyboard Lock + fullscreen; the lock + pause/resume path is the
|
|
261
|
+
non-negotiable part.
|
|
255
262
|
- **Dashboard embed:** no setup needed — the platform's game frame grants keyboard
|
|
256
263
|
lock (and pointer lock + fullscreen), so Escape-to-pause works the same inside
|
|
257
264
|
`/world/` + `/draft/` as it does standalone (`<slug>.genex.technology`).
|
|
@@ -261,6 +268,28 @@ menu — trackpads feel slower than mice, so let the player tune it. On the bund
|
|
|
261
268
|
camera the setter is live: `slider.oninput = () => { followCam.aimSensitivity = +slider.value; };`
|
|
262
269
|
(radians per pixel; default `0.0023`, a usable range is ~`0.0008`–`0.005`).
|
|
263
270
|
|
|
271
|
+
## The cursor during play: locked or a tool
|
|
272
|
+
|
|
273
|
+
During play the OS cursor is either the gameplay tool (cursor-core: click-to-move,
|
|
274
|
+
tower defense, builders, card/board — it stays visible, that's correct) or it is
|
|
275
|
+
**locked away — including keyboard-only games** (racer, platformer, runner): an
|
|
276
|
+
arrow parked over the action for the whole session is a shipped defect. Games on
|
|
277
|
+
the bundled `FollowCamera` get the lock free (on by default). A hand-rolled game
|
|
278
|
+
locks with ~6 lines, reusing this section's Escape flow:
|
|
279
|
+
|
|
280
|
+
```ts
|
|
281
|
+
// In the Play/Start/Resume CLICK handler (lock needs a user gesture):
|
|
282
|
+
canvas.requestPointerLock?.(); // hides the cursor, focuses the game
|
|
283
|
+
// Already in the Escape recipe above: pointerlockchange → if unlocked while
|
|
284
|
+
// playing, pause; the Resume click re-locks. Keyboard games need nothing more —
|
|
285
|
+
// no reticle, no aim code; the lock just parks the cursor.
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
If the lock is genuinely unavailable (a third-party embed without
|
|
289
|
+
`allow="pointer-lock"`), fall back to hiding the idle cursor over the canvas:
|
|
290
|
+
`canvas.style.cursor = "none"` after ~2s without `pointermove`, restored
|
|
291
|
+
instantly on move. Menus and pause screens always keep their cursor.
|
|
292
|
+
|
|
264
293
|
## The loader
|
|
265
294
|
|
|
266
295
|
The loader is the first thing every player sees — a bare "Loading… 3/5" over
|
|
@@ -399,6 +428,9 @@ architecture and consume the shared style brief.
|
|
|
399
428
|
- HUD sprites never enqueued at the gate — the placeholder CSS shipped as the
|
|
400
429
|
final HUD.
|
|
401
430
|
- No pause screen, or a pause that isn't bound to Escape.
|
|
431
|
+
- The OS arrow parked over the action for the whole session in a keyboard-driven
|
|
432
|
+
game (the cursor is either a gameplay tool or locked away — see the cursor
|
|
433
|
+
section).
|
|
402
434
|
- A style brief whose fonts were never actually loaded (a system-stack display
|
|
403
435
|
font at runtime).
|
|
404
436
|
- A micro-element (reticle, cue, toast, damage number) left as default CSS
|
|
@@ -15,7 +15,7 @@ map, execution order, and acceptance gate.
|
|
|
15
15
|
|
|
16
16
|
| Work needed | Load |
|
|
17
17
|
| --- | --- |
|
|
18
|
-
| 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, floating origins | `$genex-threejs-camera-direction` |
|
|
18
|
+
| 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` |
|
|
19
19
|
| 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` |
|
|
20
20
|
| 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` |
|
|
21
21
|
| the player drives or flies something: cars, drones, vehicle physics, gearbox, enter/exit between character and vehicle | `$genex-threejs-vehicle-controllers` |
|
|
@@ -204,8 +204,16 @@ concept-driven — a richer first build beats a grey-box one.
|
|
|
204
204
|
drag-orbit (`pointerLockAim: false`) only with a stated reason (e.g. a
|
|
205
205
|
cursor-heavy UI core). **Never** — cursor-core games (click-to-move, tower
|
|
206
206
|
defense, builder, card/puzzle), orbit showcases, touch-only; these MUST pass
|
|
207
|
-
`pointerLockAim: false`.
|
|
208
|
-
|
|
207
|
+
`pointerLockAim: false`. Keyboard-only games (racer, platformer) lock too —
|
|
208
|
+
the cursor is either a gameplay tool or locked away during play. The mechanism
|
|
209
|
+
and the full aim contract live in `$genex-threejs-camera-direction`.
|
|
210
|
+
- Input direction (always — every game that moves with keys or pointer):
|
|
211
|
+
D/ArrowRight must move or turn the player screen-RIGHT, mouse-right must turn
|
|
212
|
+
the view right, drag-pan axes share one convention. The screen-direction
|
|
213
|
+
contract and verified copy-paste bases live in
|
|
214
|
+
`$genex-threejs-camera-direction` — hand-rolled steering/pan/look math copies
|
|
215
|
+
one instead of deriving signs, and the smoke check's input-direction pass
|
|
216
|
+
verifies it.
|
|
209
217
|
- Art direction follows THIS game's concept. The style examples inside skills
|
|
210
218
|
are examples, not defaults — never default to neon/cyberpunk/synthwave (or any
|
|
211
219
|
other single register) unless the concept calls for it.
|
|
@@ -222,7 +230,7 @@ concept-driven — a richer first build beats a grey-box one.
|
|
|
222
230
|
- Use `$genex-threejs-visual-validation` before declaring graphics/procedural-system
|
|
223
231
|
work done. **Game fast path:** for game tasks that loaded no procedural/visual-system
|
|
224
232
|
skill, done = a screenshot plus an interaction smoke check (load the page, press each
|
|
225
|
-
control, see the visible response) — don't run the full diagnostic gate — PLUS the
|
|
233
|
+
control, see the visible response in its labeled direction) — don't run the full diagnostic gate — PLUS the
|
|
226
234
|
floors from the routing-map's acceptance gate: the generated sprite HUD wired in
|
|
227
235
|
(not the CSS placeholder), pause on Escape, the branded loader with its key-art
|
|
228
236
|
background, the brief's fonts actually loaded, the renderer baseline + at least one
|
|
@@ -180,7 +180,10 @@ Three.js release or branch, and do not blindly copy demo architecture.
|
|
|
180
180
|
(`$genex-threejs-visual-validation` owns the capture discipline).
|
|
181
181
|
7. Add camera direction when framing, controls, transitions, or scale perception
|
|
182
182
|
affect play — or the game aims with the mouse (shooter/FPS/turret): the
|
|
183
|
-
step-4 bucket decision executes here.
|
|
183
|
+
step-4 bucket decision executes here. And before ANY hand-rolled
|
|
184
|
+
steering/pan/look math: the screen-direction contract (D → screen-right,
|
|
185
|
+
mouse-right → view right, drag axes one convention) with verified copy-paste
|
|
186
|
+
bases lives there — signs are copied, never derived.
|
|
184
187
|
8. Add procedural animation when object motion needs authored phases,
|
|
185
188
|
convergence, looping, or deterministic timelines.
|
|
186
189
|
9. Add shared fields before writing multiple independent noise layers.
|
|
@@ -250,7 +253,7 @@ module — a corrupted entry point costs more than the minutes saved.
|
|
|
250
253
|
|
|
251
254
|
**Game fast path:** for a game task that loaded no procedural/visual-system skill,
|
|
252
255
|
done = a screenshot plus an interaction smoke check (load the page, press each
|
|
253
|
-
control, assert a visible response — `$genex-threejs-visual-validation` has the
|
|
256
|
+
control, assert a visible response in its labeled direction — `$genex-threejs-visual-validation` has the
|
|
254
257
|
procedure), **plus the UI floor from `$genex-threejs-game-ui` (the generated
|
|
255
258
|
sprite HUD wired in — not the CSS placeholder — pause on Escape, the branded
|
|
256
259
|
loader with its key-art background, the brief's font pair actually loaded)
|
|
@@ -75,6 +75,10 @@ Pick what matches the game; most games need exactly one or two of these.
|
|
|
75
75
|
lives on the stick; the static circle is fine for slower games. On the
|
|
76
76
|
bundled character controller, pass it through instead — see
|
|
77
77
|
`$genex-threejs-character-controller` (`joystick: { x: joy.x, y: joy.y }`).
|
|
78
|
+
Touch axes obey the same screen-direction contract as WASD and the mouse
|
|
79
|
+
(`$genex-threejs-camera-direction`): stick-right must move the player
|
|
80
|
+
screen-right, drag-right must turn the view right — a flipped feel is a sign
|
|
81
|
+
bug in the mapping, never a device quirk.
|
|
78
82
|
- **Camera look → drag zone on the right half.** Default `DragZone()` is
|
|
79
83
|
exactly that; per frame `const { dx, dy } = look.consumeDelta()` then apply
|
|
80
84
|
to yaw/pitch with the same sensitivity scale as the mouse path. Games on the
|
|
@@ -72,9 +72,17 @@ everything twice.
|
|
|
72
72
|
skill's "Self-testing a draft" section) — so you see the game, not the
|
|
73
73
|
sign-in gate.
|
|
74
74
|
2. Press each documented control once (keys, pointer); assert a **visible
|
|
75
|
-
response
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
response in its labeled direction** — this is the input-direction pass, and
|
|
76
|
+
it is part of THIS check, not an extra testing loop. Hold `KeyD`/ArrowRight
|
|
77
|
+
~0.5s and screenshot-diff: the controlled thing moves or turns toward
|
|
78
|
+
screen-RIGHT (for a pan camera the viewport slides right — the terrain
|
|
79
|
+
streams LEFT); `KeyA`/ArrowLeft mirrors it. Keyboard synthesis needs no
|
|
80
|
+
pointer lock, so this works headless. For drag rigs, drag right AND drag up:
|
|
81
|
+
both axes must follow the one stated convention (grab-the-world or
|
|
82
|
+
move-the-camera — never one each). A response in the WRONG direction is a
|
|
83
|
+
fail, not a note: two shipped games passed "controls respond" while D
|
|
84
|
+
steered screen-left. For an animated character, capture idle, walk, run,
|
|
85
|
+
crouch-idle, crouch-move, and jump. Inspect shoulders, elbows, wrists, and hands as well
|
|
78
86
|
as the feet: a fully bound non-T-pose can still be stylistically broken.
|
|
79
87
|
Reject shrugging palms-up poses, permanently raised elbows, or a gait whose
|
|
80
88
|
upper-body style contradicts the requested character. “No T-pose” is not
|
|
@@ -104,16 +112,19 @@ everything twice.
|
|
|
104
112
|
floating above detached wheels means the model was box-fit against the
|
|
105
113
|
preset's wheelbase (the vehicle skill's "Custom generated bodies" rules
|
|
106
114
|
fix it).
|
|
107
|
-
6.
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
115
|
+
6. The cursor pass — every game, per the lock-or-tool rule: during play the OS
|
|
116
|
+
cursor is either the gameplay tool (cursor-core — confirm the explicit
|
|
117
|
+
`pointerLockAim: false` opt-out, cursor stays) or it is LOCKED away; a
|
|
118
|
+
non-cursor-core game with the arrow parked over the action is a defect, even
|
|
119
|
+
a keyboard-only racer. Aim games additionally: click the canvas and assert
|
|
120
|
+
the pointer locks (cursor gone, mouse-RIGHT turns the view RIGHT and
|
|
121
|
+
mouse-UP looks UP — name BOTH axes; yaw-only evidence has let inverted pitch
|
|
122
|
+
ship); press Esc and assert the "click to aim/resume" cue appears. The cue
|
|
123
|
+
should be the bundled `createAimCue` helper (or an equivalent
|
|
112
124
|
`onAimChange`-driven overlay) — a MANDATORY-bucket game with no unlocked cue
|
|
113
|
-
fails.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
say plainly that the lock itself needs one manual click.
|
|
125
|
+
fails. Headless caveat: `requestPointerLock` throws in headless Chromium —
|
|
126
|
+
assert the wiring and the unlocked cue in a screenshot, and say plainly that
|
|
127
|
+
the lock itself needs one manual click (do the both-axes look check there).
|
|
117
128
|
7. **Ask the scene the three things the screenshot cannot answer** (below). Run it
|
|
118
129
|
once, in the same browser you already have open.
|
|
119
130
|
|
|
@@ -279,6 +290,12 @@ visual-system work — the sequence above.
|
|
|
279
290
|
|
|
280
291
|
- a MANDATORY-bucket aim game never requests pointer lock, or locks with no
|
|
281
292
|
visible unlocked cue;
|
|
293
|
+
- a movement key or look axis whose on-screen direction contradicts its label
|
|
294
|
+
(D turning the vehicle screen-left, mouse-up looking down with no invert
|
|
295
|
+
option);
|
|
296
|
+
- drag-pan axes that mix conventions (one axis grab-the-world, the other
|
|
297
|
+
move-the-camera);
|
|
298
|
+
- a non-cursor-core game that leaves the OS cursor visible during play;
|
|
282
299
|
- approval relies on a single frame;
|
|
283
300
|
- post-processing cannot be disabled per pass;
|
|
284
301
|
- random seeds are not reproducible;
|