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.
5.7 KiB
| name | description |
|---|---|
| makepad-game-ui-designer | Design and build Makepad game UI: HUD, menus, pause and win/lose overlays, settings, responsive and touch layout, XR-safe interfaces, and splash-DSL styling. Use for HUD, menu, overlay, scoreboard, minimap, prompt, controls screen, mobile layout, and UI polish work in makepad-widgets and makepad-game-render's hud module. |
Makepad Game UI Designer
Game UI is not app UI. It is read in peripheral vision, during motion, while the player is doing something else. Legibility and latency beat elegance.
Two surfaces
In-world / overlay HUD — drawn by the renderer, inside the 3D pass: makepad-game-render::hud (draw_hud_overlay, draw_billboard_labels, thermometer), with sim-side HUD state in makepad-game-sim::hud. Script verbs: text, bar, crosshair, label, label_text.
Use this for anything that must sit with the world: damage numbers, billboard nameplates, interaction prompts, crosshair, world-anchored markers. It is also the only correct choice in XR.
Widget UI — ordinary makepad-widgets composed in script_mod!. Use for menus, settings, pause, results screens, chat, and anything with real interaction and focus.
Do not put a health bar in a widget layer that must update every frame if the HUD path already does it — you will pay a layout pass for a number.
Styling with script_mod!
script_mod! {
use mod.prelude.widgets_internal.*
use mod.widgets.*
mod.widgets.GameHudBase = #(GameHud::register_widget(vm))
mod.widgets.GameHud = set_type_default() do mod.widgets.GameHudBase {
width: Fill
height: Fill
draw_bg += { /* look only */ }
}
}
Look lives in the DSL, structure and behaviour in Rust. Inheritance (+= / do) is how a variant is made — copy-pasting a whole widget definition to change one colour is how a theme becomes unmaintainable.
The splash DSL resolves at runtime: a malformed style or a missing widget id survives cargo check and fails on launch. Always run the app after a UI change.
The states that must exist
Every one needs a visible surface. Missing states are the most common UI gap in a game that "works".
| State | Must show |
|---|---|
| Boot / loading | that something is happening, and progress if it takes > 1 s |
| Menu | start, and how to control the game |
| Playing | the HUD, and nothing else |
| Paused | that it is paused, resume, restart, quit |
| Win | the outcome, the score, what to do next |
| Lose | the outcome, why, retry |
| Settings | audio, controls, quality |
Two recurring bugs: pause that does not stop the sim step, and retry that leaves the previous run's score, timers or audio voices alive. Reset through one reset() and test by winning twice in a row.
HUD principles
- Only what changes the next decision. Everything else is clutter. A stat card of nine numbers is a placeholder, not a HUD.
- Position by urgency. Critical and instantaneous → near the centre or the crosshair. Ambient → corners.
- Readable in motion. High contrast against the busiest frame in the game, not the menu background. Outline or shadow text over the world — a thin light font on a bright sky is invisible exactly when it matters.
- Animate value changes. A health bar that jumps is missed; one that drains over ~0.2 s with a lagging damage ghost is felt.
- Diegetic where it fits — a speedometer on the dashboard beats a corner number in a driving game.
- Nothing decorative that moves. Motion in the periphery reads as a threat; spend that signal on real events.
Responsive and touch
Layout with Fill, Fit and fractional sizing; the fork's turtle layout also has Grid (added in recent upstream work). Do not hardcode pixel positions for anything that must survive an aspect-ratio change.
- Test at 16:9, 4:3, and a tall phone ratio at minimum. Anchor to edges, not to absolute coordinates.
- Safe area: keep essential UI out of the outer ~5%, and away from notches and rounded corners.
- Touch targets ≥ 44 px at the real device DPI. Thumbs occlude what they touch — put virtual controls where the hand already is (lower corners), and make virtual sticks relative to first touch, not fixed.
- No hover states on touch. If information only appears on hover, it does not exist on mobile.
XR
xr/ and apps/arcade/src/xr_input.rs. Rules that are not optional:
- Never face-lock UI. Head-locked panels cause sickness. Anchor to the world, to the wrist, or to a comfortable body-relative position that lags the head.
- Keep panels ~1–2 m away; nearer than ~0.5 m cannot be focused.
- Text must be far larger than a screen equivalent; thin fonts vanish.
- Pointing is coarse — targets need to be much bigger than on desktop.
- No shake, no rapid full-field flashes.
Accessibility
Cheap, and it improves the game for everyone: never encode meaning in hue alone (pair with shape/icon/position); keep body text ≥ 16 px equivalent; provide a way to reduce shake and flashes; make control prompts show the active device's glyphs, not a hardcoded keyboard key.
Verification
makepad-test drives the real UI:
app.widget_dump(); // the tree, for finding ids
app.widget_snapshot(); // Vec<WidgetSnapshot> - assert structure/state
app.screenshot(); // look at it
app.press_key(KeyCode::Escape);
app.touch_down(x, y);
Capture every state at the target aspect ratio and inspect the images. A UI change verified only by cargo check is unverified — the DSL resolves at runtime.
Required reading
references/hud-patterns.md— layouts per genre, anti-patterns, animation timings.references/menus-and-flow.md— state machine, focus, settings, results screens.