The directive was that the demo scene become a project template you can make new worlds from and edit by voice. This is the blocker gone: an authored splash file can now build the world the demo builds. `apps/arcade/resources/template.splash` is that world — sky, sun, terrain, crossroads, two rows of houses, six distinct drivable cars, a bearded hero, wandering townsfolk and the spiral climb — entirely in `game.*` verbs. It loads: "eval ok, 28 entities, 5 skinned characters". Two engine gaps had to close first, and both were the same shape: arcade owned something the script could not reach. **The script could not see the asset library.** `ScriptHost::set_assets` existed and arcade never called it, so every asset verb — find_model, model, kits, cast — reported "no stock library on this device" on a machine with 4,700 models on disk. arcade built an index for its own Rust demo and kept it. An authored game therefore could not use any of the art the demo is made of, which is most of the reason the demo had to stay in Rust. The index is now built once, lazily, and shared with the host. **Script characters had no bodies.** The skinned draw path walks `self.villagers`, which only the built-in Rust world ever filled, so every character in an authored game rendered as its bare collision box — which is what a splash world looked like next to the demo. `sync_script_characters` now builds that list from `blocks.characters` after each eval, matching the model id the script asked for against the loaded cast and round-robining on a miss. A wrong-looking character beats an invisible one. Not yet done, and the template is honest about which parts are which: the climb's moving lifts and the fireworks still have no verb, and the world is written out longhand where the Rust version used loops. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| examples | ||
| resources | ||
| src | ||
| BUDGETS.md | ||
| build.rs | ||
| Cargo.toml | ||
| download_assets.sh | ||
| README.md | ||
Makepad Arcade
Networked AI game sandbox (plan: repo-root game.md). Run with:
cargo run -p makepad-arcade
Stock assets
Arcade ships with a searchable library of CC0 models and sounds. The binaries are not vendored in git — fetch them once:
./apps/arcade/download_assets.sh # core packs, ~75 MB
./apps/arcade/download_assets.sh --packs=all # everything, ~185 MB
./apps/arcade/download_assets.sh --list # show packs, download nothing
The default fetches a core set (~1900 models) so a fresh clone isn't forced
to pull the lot; --packs=all gets the full Kenney 3D catalogue (4669 models
across 47 packs), and --packs=nature-kit,car-kit picks specific ones. Add
the 556 sounds and the nine rigged KayKit characters and the full library is
~5000 searchable assets — of which 36 are rigged and animated.
Everything is gitignored and pinned — starter kits to exact GitHub commits, the rest to content-hashed kenney.nl URLs — and every file is sha256-verified, so a moved or tampered upstream fails loudly instead of silently changing the library. Downloads are sequential with a delay: this is someone else's bandwidth.
Mirroring
resources/MIRROR.toml lists every pack with its canonical URL, sha256, size
and model count. Because these assets are CC0, anyone may re-host them, and
that file is what makes a mirror reproducible and verifiable. Point at one with:
ARCADE_ASSET_MIRROR=https://your.host/assets ./apps/arcade/download_assets.sh
./apps/arcade/download_assets.sh --mirror=https://your.host/assets
A mirror is expected to serve <base>/<slug>.zip. The sha256 from
MIRROR.toml is verified identically whichever host served the bytes — a
mirror is never trusted more than upstream; the hash is the authority.
Everything degrades gracefully without them: the demo runs with primitive shapes, and tests that need real assets skip with a hint.
Audio is Ogg Vorbis. Every Kenney audio pack ships .ogg only — no WAV
variant exists upstream — and this tree has no vorbis decoder. The sounds are
therefore indexed and searchable by the AI but not yet playable; adding a
decoder (or running download_assets.sh --transcode, which converts to WAV
when ffmpeg is installed) is what closes that gap.
Finding assets
The library is queried by description, never by filename, via
makepad-game-assets. The agent gets a find_model tool and a one-paragraph
summary — it searches, it never receives the catalogue (5000 entries would not
fit in a prompt, and the summary stays ~480 characters however large the
library grows). Ids look like kenney/racing/vehicle-truck-yellow and are
stable across re-downloads, because generated game code writes them.
Findability is built in three layers so it scales past 4000 models: per-pack theme curation (~55 rows, giving every model its setting), filename token parsing (free, and Kenney's names are systematic), and a hand-curated query-time synonym table (~240 rows) that applies to the whole catalogue at once. Item-level curation is spent only on the few hundred most-requested things. At the full 4,999-entry catalogue: index build ~120 ms, a search ~0.2 ms, ~2.1 MB of heap (release).
Query-side stemming means an inflected request still reaches a base-form
alias ("smashing" → the smash alias), and when two entries tie on score the
kind the query implies wins — an unqualified noun like "spaceship" is an
object request, while "metal clang" or "win music" wants something audible.
Credits
Every asset here is CC0 (public domain). Attribution isn't required by the licence — we credit anyway, because these libraries exist because someone chose to give them away.
- Kenney — https://kenney.nl/assets — 47 model packs totalling ~4,670 models (nature, city, castle, space, food, furniture, vehicles, dungeons, characters and more), the five starter kits, and all seven sound packs (impact, interface, sci-fi, music jingles, UI, RPG and digital audio). Thank you for the extraordinary breadth of free, consistent, genuinely usable game assets — this library is most of what Arcade can build with.
- KayKit / Kay Lousberg — https://kaylousberg.itch.io/ — nine rigged and animated characters: five adventurers (Knight, Barbarian, Mage, Rogue, Rogue_Hooded) and four skeletons (Warrior, Mage, Rogue, Minion). All nine share one 41-joint skeleton, so an animation authored for any of them plays on every one — the adventurers ship 76 clips and the skeletons those same 76 plus 19 undead extras. Thank you for giving away rigs and animation sets, which are the expensive part.
Rigged characters
find_cast lists the animated casts. A cast is a set of characters sharing one
skeleton, so any state works on any member and a part can be recast without
touching animation code:
| rig | members | clips | notable states |
|---|---|---|---|
| 41 joints (KayKit) | 9 | 76–95 | block, dodge, hurt, dance, sleep, carry |
| 7 joints (Kenney mini) | 22 | 25–32 | walk, run, jump, attack, sit, wave |
| 6 joints (Kenney platformer) | 5 | 25 | walk, run, jump, attack |
Pick members from ONE cast for a scene, and use different members so a crowd isn't clones — the same rule that applies to props.
Machine-readable attribution lives in resources/CREDITS.toml so a published
game package can carry credit with it.