makepad/skills/makepad-3d-generator/references/procedural-recipes.md
Arena Agent fe21c07d84 skills: add Makepad game skills pack ported from threejs-game-skills
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.
2026-09-05 21:18:58 +00:00

92 lines
5.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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