Add two tutorial games that build, run in CI, and cannot drift
examples/sidescroller and examples/jrpg are complete programs, built with the
library and exercised headless by ctest. The chapters quote them with
`c excerpt=examples/...` blocks rather than restating the code, so a chapter
cannot drift from a program that compiles -- the excerpt check fails the moment
the source moves. 34 excerpts in one chapter, 21 in the other.
The two are complementary. The sidescroller is the physics tutorial: gravity, a
jump, coins, hazards. The JRPG is the content-pipeline tutorial: a town map,
NPCs spawned from map objects, four-way per-facing animation, a text box, a
follower.
Both smoke tests drive real SDL_Events through akgl_controller_handle_event and
step the physics clock at a fixed 1/60s rather than sleeping, so a scripted run
is deterministic and finishes in under five seconds.
Writing them is what turned up most of the defects recorded in the next commit,
because a game exercises paths a unit test does not. Each workaround says in the
chapter which library gap forced it:
- collision is written in a custom movementlogicfunc, because
akgl_physics_arcade_collide raises AKERR_API and akgl_physics_simulate never
calls collide at all;
- the sidescroller cancels the step's own gravity when it blocks downward,
because otherwise a quarter-pixel of penetration makes the *horizontal* sweep
report blocked and the character walks backwards a tile at a time;
- both clear movement_controls_face on every map-spawned actor, because the
default facefunc leaves a stopped actor with no facing bit, no sprite, and no
draw;
- the JRPG's follower gets a renderfunc that nulls obj->parent for the duration
of the draw, because a child's offset is counted twice.
Assets are CC0 from three Kenney packs, vendored with per-pack licence text,
per-file provenance, and the geometry contract in
docs/tutorials/assets/README.md. CC0 specifically rather than merely free: a
reader who copies a tutorial into their own game inherits no obligation.
scripts/fetch_tutorial_assets.sh refreshes them in the shape
mkcontrollermappings.sh was fixed into for 0.5.0 -- it checks curl's status,
refuses a pack page that does not say CC0, verifies the archive and the staged
dimensions, and leaves the tracked bytes untouched on any failure. Both failure
paths were tested, and a no-op refresh is byte-identical.
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 20:59:00 -04:00
|
|
|
{
|
|
|
|
|
"compressionlevel": -1,
|
|
|
|
|
"height": 20,
|
|
|
|
|
"infinite": false,
|
|
|
|
|
"layers": [
|
|
|
|
|
{
|
|
|
|
|
"data": [
|
|
|
|
|
1,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
2,
|
|
|
|
|
3,
|
|
|
|
|
28,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
30,
|
|
|
|
|
28,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
90,
|
|
|
|
|
91,
|
|
|
|
|
91,
|
|
|
|
|
91,
|
|
|
|
|
91,
|
|
|
|
|
91,
|
|
|
|
|
91,
|
|
|
|
|
91,
|
|
|
|
|
91,
|
|
|
|
|
92,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
30,
|
|
|
|
|
28,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
117,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
119,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
171,
|
|
|
|
|
172,
|
|
|
|
|
172,
|
|
|
|
|
172,
|
|
|
|
|
173,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
30,
|
|
|
|
|
28,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
117,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
119,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
198,
|
|
|
|
|
199,
|
|
|
|
|
199,
|
|
|
|
|
199,
|
|
|
|
|
200,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
30,
|
|
|
|
|
28,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
117,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
119,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
198,
|
|
|
|
|
199,
|
|
|
|
|
199,
|
|
|
|
|
199,
|
|
|
|
|
200,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
30,
|
|
|
|
|
28,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
117,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
119,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
198,
|
|
|
|
|
199,
|
|
|
|
|
199,
|
|
|
|
|
199,
|
|
|
|
|
200,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
30,
|
|
|
|
|
28,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
117,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
119,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
225,
|
|
|
|
|
226,
|
|
|
|
|
226,
|
|
|
|
|
226,
|
|
|
|
|
227,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
30,
|
|
|
|
|
28,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
117,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
119,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
30,
|
|
|
|
|
28,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
117,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
119,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
30,
|
|
|
|
|
28,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
117,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
119,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
30,
|
|
|
|
|
28,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
117,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
119,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
30,
|
|
|
|
|
28,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
117,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
119,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
30,
|
|
|
|
|
28,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
117,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
119,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
30,
|
|
|
|
|
28,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
117,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
119,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
30,
|
|
|
|
|
28,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
117,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
119,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
30,
|
|
|
|
|
28,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
117,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
118,
|
|
|
|
|
119,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
30,
|
|
|
|
|
28,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
144,
|
|
|
|
|
145,
|
|
|
|
|
145,
|
|
|
|
|
145,
|
|
|
|
|
145,
|
|
|
|
|
145,
|
|
|
|
|
145,
|
|
|
|
|
145,
|
|
|
|
|
145,
|
|
|
|
|
146,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
30,
|
|
|
|
|
28,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
29,
|
|
|
|
|
30,
|
|
|
|
|
55,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
56,
|
|
|
|
|
57
|
|
|
|
|
],
|
|
|
|
|
"height": 20,
|
|
|
|
|
"id": 1,
|
|
|
|
|
"name": "ground",
|
|
|
|
|
"opacity": 1,
|
|
|
|
|
"type": "tilelayer",
|
|
|
|
|
"visible": true,
|
|
|
|
|
"width": 30,
|
|
|
|
|
"x": 0,
|
|
|
|
|
"y": 0
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": [
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
233,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
234,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
260,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
261,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
73,
|
|
|
|
|
73,
|
|
|
|
|
73,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
100,
|
|
|
|
|
284,
|
|
|
|
|
100,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
234,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
261,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
233,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
260,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
73,
|
|
|
|
|
73,
|
|
|
|
|
73,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
100,
|
|
|
|
|
284,
|
|
|
|
|
100,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
234,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
261,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
233,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
233,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
260,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
260,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0
|
|
|
|
|
],
|
|
|
|
|
"height": 20,
|
|
|
|
|
"id": 2,
|
|
|
|
|
"name": "decoration",
|
|
|
|
|
"opacity": 1,
|
|
|
|
|
"type": "tilelayer",
|
|
|
|
|
"visible": true,
|
|
|
|
|
"width": 30,
|
|
|
|
|
"x": 0,
|
Delete the JRPG's collision too, and wall the map with proxies
cell_solid and feet_blocked go, and so does the prediction in the player's
movementlogicfunc. That prediction was only ever exact because the town has zero
gravity and zero drag -- v is t, so `x + tx * dt` is where the step lands. A map
with gravity would have had to fold ey in as well, which is the game
re-implementing the integrator. Resolution runs after the move now, so there is
nothing to predict.
The map's decoration layer carries `collidable`, which retires JRPG_LAYER_SOLID:
akgl_TilemapLayer has no name member, so the game and the map had to agree on an
index out of band and inserting a layer in Tiled broke it.
The edge of the world is not on any layer, so it is four static proxies covering
the outer ring plus a tile of overhang -- one pool slot per side instead of a
hundred solid tiles, and the first use of the static-proxy path in either
example. They carry LAYER_STATIC explicitly: shape_box defaults a shape to
LAYER_ACTOR, and a wall left on that layer is a wall everything walks through.
Only the player gets a shape. NPCs stand still and are spoken to; the follower
is a child snapped to its parent every step.
Verified against the old implementation with the demo script rewritten to hold
one direction: holding left into a building stops the player at x=122 with both,
and holding up into the map's edge stops them at y=-4 with both.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KzBDV2fqgnUAcqCKqKvc71
2026-08-02 07:46:19 -04:00
|
|
|
"y": 0,
|
|
|
|
|
"properties": [
|
|
|
|
|
{
|
|
|
|
|
"name": "collidable",
|
|
|
|
|
"type": "bool",
|
|
|
|
|
"value": true
|
|
|
|
|
}
|
|
|
|
|
]
|
Add two tutorial games that build, run in CI, and cannot drift
examples/sidescroller and examples/jrpg are complete programs, built with the
library and exercised headless by ctest. The chapters quote them with
`c excerpt=examples/...` blocks rather than restating the code, so a chapter
cannot drift from a program that compiles -- the excerpt check fails the moment
the source moves. 34 excerpts in one chapter, 21 in the other.
The two are complementary. The sidescroller is the physics tutorial: gravity, a
jump, coins, hazards. The JRPG is the content-pipeline tutorial: a town map,
NPCs spawned from map objects, four-way per-facing animation, a text box, a
follower.
Both smoke tests drive real SDL_Events through akgl_controller_handle_event and
step the physics clock at a fixed 1/60s rather than sleeping, so a scripted run
is deterministic and finishes in under five seconds.
Writing them is what turned up most of the defects recorded in the next commit,
because a game exercises paths a unit test does not. Each workaround says in the
chapter which library gap forced it:
- collision is written in a custom movementlogicfunc, because
akgl_physics_arcade_collide raises AKERR_API and akgl_physics_simulate never
calls collide at all;
- the sidescroller cancels the step's own gravity when it blocks downward,
because otherwise a quarter-pixel of penetration makes the *horizontal* sweep
report blocked and the character walks backwards a tile at a time;
- both clear movement_controls_face on every map-spawned actor, because the
default facefunc leaves a stopped actor with no facing bit, no sprite, and no
draw;
- the JRPG's follower gets a renderfunc that nulls obj->parent for the duration
of the draw, because a child's offset is counted twice.
Assets are CC0 from three Kenney packs, vendored with per-pack licence text,
per-file provenance, and the geometry contract in
docs/tutorials/assets/README.md. CC0 specifically rather than merely free: a
reader who copies a tutorial into their own game inherits no obligation.
scripts/fetch_tutorial_assets.sh refreshes them in the shape
mkcontrollermappings.sh was fixed into for 0.5.0 -- it checks curl's status,
refuses a pack page that does not say CC0, verifies the archive and the staged
dimensions, and leaves the tracked bytes untouched on any failure. Both failure
paths were tested, and a no-op refresh is byte-identical.
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 20:59:00 -04:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"draworder": "topdown",
|
|
|
|
|
"id": 3,
|
|
|
|
|
"name": "actors",
|
|
|
|
|
"objects": [
|
|
|
|
|
{
|
|
|
|
|
"height": 32,
|
|
|
|
|
"id": 1,
|
|
|
|
|
"name": "player",
|
|
|
|
|
"properties": [
|
|
|
|
|
{
|
|
|
|
|
"name": "character",
|
|
|
|
|
"type": "string",
|
|
|
|
|
"value": "jrpg_player"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"name": "state",
|
|
|
|
|
"type": "int",
|
|
|
|
|
"value": 17
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"rotation": 0,
|
|
|
|
|
"type": "actor",
|
|
|
|
|
"visible": true,
|
|
|
|
|
"width": 32,
|
|
|
|
|
"x": 224,
|
|
|
|
|
"y": 256
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"height": 32,
|
|
|
|
|
"id": 2,
|
|
|
|
|
"name": "shopkeeper",
|
|
|
|
|
"properties": [
|
|
|
|
|
{
|
|
|
|
|
"name": "character",
|
|
|
|
|
"type": "string",
|
|
|
|
|
"value": "jrpg_shopkeeper"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"name": "state",
|
|
|
|
|
"type": "int",
|
|
|
|
|
"value": 17
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"rotation": 0,
|
|
|
|
|
"type": "actor",
|
|
|
|
|
"visible": true,
|
|
|
|
|
"width": 32,
|
|
|
|
|
"x": 80,
|
|
|
|
|
"y": 128
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"height": 32,
|
|
|
|
|
"id": 3,
|
|
|
|
|
"name": "elder",
|
|
|
|
|
"properties": [
|
|
|
|
|
{
|
|
|
|
|
"name": "character",
|
|
|
|
|
"type": "string",
|
|
|
|
|
"value": "jrpg_elder"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"name": "state",
|
|
|
|
|
"type": "int",
|
|
|
|
|
"value": 17
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"rotation": 0,
|
|
|
|
|
"type": "actor",
|
|
|
|
|
"visible": true,
|
|
|
|
|
"width": 32,
|
|
|
|
|
"x": 272,
|
|
|
|
|
"y": 112
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"opacity": 1,
|
|
|
|
|
"type": "objectgroup",
|
|
|
|
|
"visible": true,
|
|
|
|
|
"x": 0,
|
|
|
|
|
"y": 0
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"nextlayerid": 4,
|
|
|
|
|
"nextobjectid": 4,
|
|
|
|
|
"orientation": "orthogonal",
|
|
|
|
|
"properties": [
|
|
|
|
|
{
|
|
|
|
|
"name": "physics.model",
|
|
|
|
|
"type": "string",
|
|
|
|
|
"value": "arcade"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"name": "physics.gravity.x",
|
|
|
|
|
"type": "float",
|
|
|
|
|
"value": 0.0
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"name": "physics.gravity.y",
|
|
|
|
|
"type": "float",
|
|
|
|
|
"value": 0.0
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"renderorder": "right-down",
|
|
|
|
|
"tiledversion": "1.8.2",
|
|
|
|
|
"tileheight": 16,
|
|
|
|
|
"tilesets": [
|
|
|
|
|
{
|
|
|
|
|
"columns": 27,
|
|
|
|
|
"firstgid": 1,
|
|
|
|
|
"image": "tiles.png",
|
|
|
|
|
"imageheight": 288,
|
|
|
|
|
"imagewidth": 432,
|
|
|
|
|
"margin": 0,
|
|
|
|
|
"name": "rpg_urban",
|
|
|
|
|
"spacing": 0,
|
|
|
|
|
"tilecount": 486,
|
|
|
|
|
"tileheight": 16,
|
|
|
|
|
"tilewidth": 16
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"tilewidth": 16,
|
|
|
|
|
"type": "map",
|
|
|
|
|
"version": "1.8",
|
|
|
|
|
"width": 30
|
|
|
|
|
}
|