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.
92 lines
5.1 KiB
Markdown
92 lines
5.1 KiB
Markdown
# Procedural recipes
|
||
|
||
`makepad-game-gen`: `mesh`, `terrain`, `tree`, `lsystem`, `spline`, `scatter`, `interior`, `kit`, `levelgen`, `implicit`, `texgen`, `cache`, `rng`.
|
||
|
||
## Determinism first
|
||
|
||
Every generator takes a seed and must produce byte-identical output on every device. Use `makepad-game-gen::rng` and `makepad-game-math` transcendentals — never `std` float math, never thread RNG. This is what allows content to replicate as `(preset, seed, position)` instead of vertex data, and it is not optional in a networked game.
|
||
|
||
```rust
|
||
#[test]
|
||
fn deterministic() {
|
||
assert_eq!(generate_forest(99), generate_forest(99));
|
||
}
|
||
```
|
||
|
||
## Terrain
|
||
|
||
`terrain` + `landform::LandKind`. Layer octaves of noise: a large-amplitude low-frequency pass for landform, a medium pass for hills, a small pass for surface break-up. Erode by lowering steep slopes toward their downhill neighbour over a few passes — this is what makes terrain read as landscape rather than as noise.
|
||
|
||
Resolution is a *visual* budget, not a sim one: 65×65 with 100 movers and 50 bodies is 0.038 ms/tick. Terrain vertices upload once per revision, so the cost is memory and vertex count, not per-frame bandwidth.
|
||
|
||
Flatten where gameplay needs flat: spawn areas, roads, building footprints. Do this **after** generation, as an explicit stamp, or you will fight the noise forever.
|
||
|
||
## Roads and rivers — `spline`
|
||
|
||
Define a centreline, sample it, extrude a cross-section along it. Stamp the terrain flat under the road before placing it, or the road will float and clip in alternating segments. Bank on curves for driving. Place checkpoints (`Checkpoint`) at spline parameters so the track and the race logic cannot disagree.
|
||
|
||
## Foliage — `tree`, `lsystem`, `scatter`
|
||
|
||
`lsystem` grows branching structures from a grammar; `tree` wraps the common cases. `scatter` distributes instances.
|
||
|
||
Scattering rules that separate a forest from a field of stamps:
|
||
|
||
- Poisson-ish spacing, not uniform random — uniform random clumps and leaves bald patches
|
||
- Seeded jitter: ±10% scale, full yaw
|
||
- Exclude by slope, by height band, and by a mask around gameplay areas
|
||
- Two or three species mixed, with one dominant
|
||
- Density falling off with distance from the player's likely path
|
||
|
||
Replicate the field as `(preset, seed, region)`, never as placements.
|
||
|
||
## Interiors — `interior`
|
||
|
||
Rooms, doors, connectivity. Validate before shipping: every room reachable, doors wide enough for the player capsule, no geometry inside the spawn.
|
||
|
||
This is exactly the case the codebase learned the hard way — `makepad-game-blocks` dev-depends on `gen` because "a walker can enter a REAL generated room" is a claim about generated geometry meeting real physics, and testing the halves separately passes while the walker floats.
|
||
|
||
## Levels — `levelgen`, `kit`, `rtsmap`
|
||
|
||
Tile-based assembly from a kit, so scale and style are consistent by construction. `kit_from_index` and `level_placements` (in `makepad-game-script::compose`) turn a kit into `PlacedTile`s. `libs/rtsmap` is the shared tiled-RTS generator.
|
||
|
||
**Always validate:**
|
||
|
||
```rust
|
||
assert!(path_exists(&level, level.spawn, level.goal), "unwinnable level, seed {seed}");
|
||
assert!(level.spawn_is_clear(), "spawn blocked, seed {seed}");
|
||
```
|
||
|
||
Run the validator over a few hundred seeds in a test. A generator that fails 1 in 50 seeds will ship, and the failures will be found by players.
|
||
|
||
## Implicit surfaces
|
||
|
||
`implicit` — SDF-style blobs, caves and smooth solids, polygonised to a mesh. Good for organic rock, cave systems and merged forms. Expensive to evaluate at high resolution: generate once, cache, do not regenerate per frame.
|
||
|
||
## Textures — `texgen`
|
||
|
||
Tiling procedural detail, packed for `DrawGameTexture`. The cheapest fix for "everything is flat colour", and it adds no download weight. Match tiling scale to world units so texel density is consistent across surfaces — inconsistent texel density is one of those defects everyone notices and few can name.
|
||
|
||
## Meshes
|
||
|
||
`mesh` builds geometry directly. Emit the packed layout `geom.GameMeshVertex` — position 3 exact f32, octahedral normal in one lane, uv 2×f16 in one lane, colour 4×unorm8 in one lane, 6 floats / 24 B total. Attributes here are f32-only; packing means bit-packing plus `unpack2f16` / `unpack4u8` in-shader.
|
||
|
||
Wind vertices consistently, generate correct normals (smooth within a surface, split at hard edges), and keep UVs inside 0..1 per island.
|
||
|
||
## Colliders
|
||
|
||
Never collide against the render mesh. Generate a simplified collider alongside: boxes and capsules for most things, a heightfield for terrain, a convex hull at worst. `model_collider_parts(id)` shows the shape the library uses.
|
||
|
||
## Caching
|
||
|
||
`cache`, keyed by `(preset, seed)`. Regenerating on demand during play is a stutter source; an unbounded cache is a leak. Bound it, and generate during loading where you can predict the need.
|
||
|
||
## Validation checklist
|
||
|
||
- [ ] Deterministic — same seed twice, byte-identical
|
||
- [ ] Scaled to the player capsule
|
||
- [ ] Packed vertex layout
|
||
- [ ] Normals correct, winding consistent
|
||
- [ ] Simplified collider present
|
||
- [ ] Spawn clear, goal reachable, validated across many seeds
|
||
- [ ] Cached with a bound
|
||
- [ ] Visually varied — jittered scale and yaw, palette tints
|