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 Co-Authored-By: Andrew Kesterson <andrew@aklabs.net>
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
#include <SDL3/SDL.h>
|
||||
#include <akerror.h>
|
||||
#include <akgl/actor.h>
|
||||
#include <akgl/collision.h>
|
||||
#include <akgl/types.h>
|
||||
|
||||
/*
|
||||
@@ -49,16 +50,6 @@
|
||||
/** @brief Point size the font is rasterized at. A size is baked into the handle. */
|
||||
#define JRPG_FONT_SIZE 12
|
||||
|
||||
/**
|
||||
* @brief Index of the tile layer this game treats as solid.
|
||||
*
|
||||
* An index, not a name, because akgl_TilemapLayer has no `name` member: the
|
||||
* loader reads a layer's `id`, `type`, `opacity`, `visible`, offset and data,
|
||||
* and drops the name Tiled wrote. A map cannot say "the layer called
|
||||
* collision", so the game and the map agree on a number. See chapter 20.
|
||||
*/
|
||||
#define JRPG_LAYER_SOLID 1
|
||||
|
||||
/** @brief Longest line an NPC can say, terminator included. */
|
||||
#define JRPG_TEXTBOX_MAX_TEXT 256
|
||||
|
||||
@@ -89,6 +80,15 @@ typedef struct {
|
||||
* @return `NULL` on success, otherwise an error context owned by the caller.
|
||||
*/
|
||||
akerr_ErrorContext AKERR_NOIGNORE *jrpg_world_load(void);
|
||||
|
||||
/**
|
||||
* @brief The collision world, owned by world.c.
|
||||
*
|
||||
* The physics backend resolves through it after every sub-move. Nothing else in
|
||||
* the game touches it: the town is walls and people, and the walls are the
|
||||
* map's own decoration layer plus four proxies around the edge.
|
||||
*/
|
||||
extern akgl_CollisionWorld jrpg_collision;
|
||||
/**
|
||||
* @brief Fix up the actors the map spawned, and attach the party member.
|
||||
*
|
||||
@@ -108,13 +108,13 @@ akerr_ErrorContext AKERR_NOIGNORE *jrpg_world_populate(void);
|
||||
*/
|
||||
akerr_ErrorContext AKERR_NOIGNORE *jrpg_camera_follow(void);
|
||||
/**
|
||||
* @brief The player's `movementlogicfunc`: the library default, plus walls.
|
||||
* @brief The player's `movementlogicfunc`: the library default, plus the freeze.
|
||||
*
|
||||
* libakgl implements no collision at all -- akgl_physics_arcade_collide raises
|
||||
* AKERR_API, akgl_physics_simulate never calls `collide`, and
|
||||
* akgl_physics_arcade_move consults no tilemap -- so a game that wants a wall
|
||||
* writes one here. Raises AKGL_ERR_LOGICINTERRUPT while the text box is open,
|
||||
* which is the documented way to tell the simulator to skip an actor's tick.
|
||||
* Walls are the library's now -- see chapter 15 -- so all this adds to
|
||||
* akgl_actor_logic_movement is raising AKGL_ERR_LOGICINTERRUPT while the text
|
||||
* box is open, which is the documented way to tell the simulator to skip an
|
||||
* actor's tick. That also skips `collide`, since the CATCH around
|
||||
* movementlogicfunc jumps past the whole rest of the step.
|
||||
*
|
||||
* @param obj The actor to compute acceleration for. Required, along with its
|
||||
* `basechar`.
|
||||
|
||||
Reference in New Issue
Block a user