Nine agent skills for building Makepad/Rust games, ported from majidmanzarpour/threejs-game-skills. Same director-routed workflow and premium bar; runtime rewritten for this fork's game crates. - makepad-game-director entrypoint, routing, continuity, asset probe - makepad-gameplay-systems loop, movers vs rigid bodies, input, camera, netplay - makepad-aaa-graphics-builder lighting, shaders, budget, visual scorecard - makepad-game-ui-designer HUD, menus, touch and XR UI - makepad-debug-profiler defect bisection and profiling - makepad-qa-release verification ladder, evidence, packaging - makepad-3d-generator CC0 model search, casts, procedural geometry - makepad-image-generator texgen textures, palettes, sky, icons - makepad-audio-generator sample bank, mixer, material impacts, 3D audio Written against the real APIs in libs/game/*, libs/sim and apps/arcade: the game.* verb table, GameRenderer adaptive quality, the packed 6-float GameMeshVertex layout, script_mod! splash styling, makepad-test driving, and the BUDGETS.md numbers. No paid generation API is required - the CC0 library plus seeded makepad-game-gen replaces them. Includes install.sh (Codex/Claude), validate-skills.sh and a repo-aware probe_assets.sh; both scripts verified against this checkout.
73 lines
3.8 KiB
Markdown
73 lines
3.8 KiB
Markdown
# Core loop, levels, difficulty
|
|
|
|
## The brief
|
|
|
|
Before code. Keep it in `artifacts/game-progress.md` and re-read it after any interruption.
|
|
|
|
```
|
|
Loop: Player drives a route, hits checkpoints, beats a lap time.
|
|
Escalate: Each lap adds traffic; the target time tightens.
|
|
Win: 3 laps under par. log "race: won"
|
|
Lose: Timer expires. log "race: lost"
|
|
Input: kb WASD+Space | pad LS+RT/LB | touch left stick + pedals
|
|
Camera: chase, 6 m back, 2.4 m up, 60 deg fov, player car 4.2 m long
|
|
Device: desktop + Quest, 72 Hz target
|
|
Art: dusk desert, warm key, long shadows, Kenney racing kit
|
|
```
|
|
|
|
Emit those exact log lines from the game. They make win/lose machine-checkable in a `makepad-test` run, which is the difference between a claim and evidence.
|
|
|
|
## Loop archetypes
|
|
|
|
| Archetype | Escalation | Ends when | Blocks to use |
|
|
| --- | --- | --- | --- |
|
|
| Race | opponents, tighter par | laps complete / time out | `Car`, `RaceKit`, `Checkpoint` |
|
|
| Arena survival | wave size and mix | player dies / wave N cleared | `Character`, `Brain`, `Npc` |
|
|
| Chase / evade | pursuer speed, spawn rate | caught / escaped | `Brain::chase`, `caught` |
|
|
| Collect | scatter distance, hazards | quota met / timer | `interactable`, `score` |
|
|
| Traversal | gap width, hazard density | goal reached / fall | mover + `deck_floor_under` |
|
|
| Flight | wind, corridor width | landed / crashed | `Plane` |
|
|
|
|
Pick one and do it well. A game that is two archetypes stapled together is usually neither.
|
|
|
|
## Level structure
|
|
|
|
Three stages, always in this order:
|
|
|
|
1. **Teach** — the mechanic in isolation, no failure possible. One idea.
|
|
2. **Test** — the same mechanic under pressure. This is most of the game.
|
|
3. **Twist** — the mechanic combined with a second one, or inverted.
|
|
|
|
Build one complete vertical slice through all three before making level 2. A slice that is wrong is cheap to fix; five levels of the same wrongness are not.
|
|
|
|
## Generating levels
|
|
|
|
`makepad-game-gen` gives `levelgen`, `kit`, `interior`, `scatter`, `terrain`, `spline`, `lsystem`, `tree`, `implicit`, `mesh`, `texgen`, all from a seeded `rng`. `makepad-game-script::compose` adds `kit_from_index`, `level_placements`, `PlacedTile`. `libs/rtsmap` is the tiled-RTS map generator shared by the importer and the sandbox.
|
|
|
|
Rules:
|
|
|
|
- A level is a **seed plus a preset**, not a vertex dump. That is what makes it replicable across the wire and cheap to store.
|
|
- Generate, then **validate**: is the goal reachable, is the spawn clear, is there a navigable path? An unvalidated generator produces unwinnable levels roughly as often as it produces good ones.
|
|
- Hand-place the things the player must notice. Scatter the rest.
|
|
|
|
## Difficulty
|
|
|
|
Tune three axes independently so a change is diagnosable: **density** (how many), **speed** (how fast), **tolerance** (how much error is forgiven — hitbox, coyote time, par time).
|
|
|
|
Widen tolerance early and narrow it late; players read tolerance as "I got better", and read density as "the game got harder". Never scale all three at once.
|
|
|
|
## State machine
|
|
|
|
Every game needs these states, and every one needs a UI surface (see `makepad-game-ui-designer`):
|
|
|
|
```
|
|
Boot -> Menu -> Playing -> Paused -> Playing
|
|
|-> Win -> Menu | Retry
|
|
|-> Lose -> Menu | Retry
|
|
```
|
|
|
|
Failure modes worth naming: pausing that does not stop the sim step; a retry that leaves score, timers, particle emitters or audio voices from the previous run alive; a win that fires twice because the condition is checked without a latch. Reset through one `reset()` that rebuilds world state, and test it by winning twice in a row.
|
|
|
|
## Scoring
|
|
|
|
Keep score in the sim (`score`, `score_of` verbs, or a sim field) — never in the widget, or it dies with the view and cannot be replicated to clients. Make it observable: log it on every change so tests can assert on it.
|