Pathfinding: tile-grid A*
Three classes, one flow: NavGrid turns the collision layer into a walkability grid, Pathfinder runs A* over it, and PathFollower steers a sprite along the result with the runner resolving actual movement. The canonical demo is examples/rpg-pathfinding/main.py.
THE GRID
A NavGrid is built from the same data the physics world uses: the flat tile map and its TilesetCollision. Tiles with solid polygons are walls; one-way tiles are still walkable surfaces.
from tilemap_parser import load_map, load_tileset_collision
from tilemap_parser.runtime.navigation import NavGrid, Pathfinder
game_data = load_map("data/map.json")
tile_map = game_data.build_tile_map() # {(col, row): tile_id}
tileset = load_tileset_collision("data/collision/terrain.collision.json")
base = NavGrid(tile_map, tileset, (32, 32), map_size=(24, 14))
nav = base.erode(1.0) # inflate walls 1 tile
pathfinder = Pathfinder(nav)
path = pathfinder.find_path((1, 1), (20, 5)) # [(tx, ty), ...] | Nonefind_path(start_tile, end_tile, max_steps=2000)returnsNonewhen the destination is unwalkable or unreachable. Path tiles are grid coordinates; multiply by the effective tile size to get world pixels (the follower does this for you).erode(margin)returns a derived grid with walls inflated by margin tiles, so entities keep a corridor from hugging walls. The example useserode(1.0).NavGrid.for_entity(...)derives the margin from a sprite size automatically:margin = (max(w, h) / 2) / tile_w.
FOLLOWING THE PATH
PathFollower walks the waypoints; each update_rpg() call moves the sprite toward the current waypoint's center at speed, resolving the move through the runner's move_rpg, and advances the waypoint on arrival (default arrival distance: 20% of a tile diagonal).
from tilemap_parser import CollisionRunner
from tilemap_parser.runtime.navigation import PathFollower
follower = PathFollower((32, 32)) # effective tile size
runner = CollisionRunner.from_game_type("rpg", (32, 32))
# In your game loop:
waypoint_idx, arrived, hit_x, hit_y = follower.update_rpg(
enemy, path, waypoint_idx,
runner, tileset, tile_map,
speed=200.0, dt=dt,
)
if arrived:
path = None # or pick a new destination- The returned tuple is
(new_waypoint_index, arrived, hit_wall_x, hit_wall_y); branch onarrivedto pick the next destination. update_rpgresolves collision againsttile_map/tileset_collisionviamove_rpg, so the follower never walks through walls; it just gets stopped and you readhit_wall_x/y.
WHEN NOT TO USE IT
This is tile-grid pathfinding: good for rooms, mazes and dungeon layouts. It does not reason about height differences, slopes, or dynamic bodies; anything that moves should be handled by your game's steering on top of the path. And for simple "chase the player" AI, steering the sprite at the target each frame is cheaper than a path.