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
This commit is contained in:
2026-08-02 07:46:19 -04:00
parent 490e62dbbf
commit cbf7c1b6c2
5 changed files with 226 additions and 156 deletions

View File

@@ -1,14 +1,14 @@
# 20. Tutorial: a 2D sidescroller
A complete game: a Tiled level, a player who runs and jumps, platforms that hold him up,
four coins to collect, a blob that patrols and a moth that flies. It is about nine hundred
lines of C — a header and four translation units, and rather more comment than that — and it
builds and runs as part of this repository's ordinary `ctest` run.
four coins to collect, a blob that patrols and a moth that flies. It is a header and three
translation units, rather more comment than code, and it builds and runs as part of this
repository's ordinary `ctest` run.
It is here for one reason above the others. **libakgl has no collision detection at all**,
and a sidescroller is the shortest path to finding that out. So this chapter is mostly about
what you write when the engine stops, and where exactly that code has to live for the frame
to come out right.
It used to be four translation units. The fourth was 383 lines of collision, and it is gone
— which makes this chapter as much about **where in the frame a thing has to happen** as
about what to write. That is the lesson that survived: the same test, run a few lines
earlier, is wrong in ways that take an afternoon to diagnose.
The program is `examples/sidescroller/`; the art, the map and the JSON are in
`docs/tutorials/assets/sidescroller/`. Every listing below is quoted straight out of those