Skip to content

PathfindingEngine

Alexandre Mondaini Calvão edited this page Dec 3, 2025 · 1 revision

PathfindingEngine

The PathfindingEngine is a self-contained pathfinding system that owns entity positions internally. This is the recommended way to use the library.

Overview

Unlike traditional approaches where the game owns positions and pathfinding is a separate service, PathfindingEngine manages everything:

  • Node graph - Waypoints and their connections
  • Entity positions - Where each entity currently is
  • Movement - Automatically moves entities along paths
  • Spatial indexing - Fast queries for nearby entities/nodes

Configuration

The engine uses comptime configuration:

const Config = struct {
    pub const Entity = u64;      // Your entity ID type
    pub const Context = *Game;   // Passed to callbacks
};

const Engine = pathfinding.PathfindingEngine(Config);

Lifecycle

// Create
var engine = try Engine.init(allocator);
defer engine.deinit();

// Build graph
try engine.addNode(0, 0, 0);
try engine.addNode(1, 100, 0);
try engine.connectNodes(.{ .omnidirectional = .{ .max_distance = 150, .max_connections = 4 } });
try engine.rebuildPaths();

// Register entities
try engine.registerEntity(player_id, 0, 0, 100.0);

// Game loop
while (running) {
    engine.tick(&game, delta_time);
}

Building the Graph

Adding Nodes

// Manual ID
try engine.addNode(0, 100, 200);  // id=0, x=100, y=200

// Auto-generated ID
const id = try engine.addNodeAuto(100, 200);  // returns assigned ID

// Bulk add
const points = [_]pathfinding.NodePoint{
    .{ .id = 0, .x = 0, .y = 0 },
    .{ .id = 1, .x = 100, .y = 0 },
    .{ .id = 2, .x = 200, .y = 0 },
};
try engine.addNodesFromPoints(&points);

Connecting Nodes

// Omnidirectional (top-down games)
try engine.connectNodes(.{
    .omnidirectional = .{
        .max_distance = 150,     // Only connect nodes within this distance
        .max_connections = 4,    // Max edges per node
    },
});

// Directional (platformers)
try engine.connectNodes(.{
    .directional = .{
        .horizontal_range = 60,  // Left/right connection range
        .vertical_range = 60,    // Up/down connection range
    },
});

Manual Edges

// Bidirectional edge
try engine.addEdge(0, 1, true);

// One-way edge (e.g., drop-down platform)
try engine.addEdge(top_node, bottom_node, false);

Rebuilding Paths

After changing the graph, rebuild Floyd-Warshall:

try engine.rebuildPaths();

Entity Management

Registration

// Register at position with speed
try engine.registerEntity(entity_id, x, y, speed);

// Remove
engine.unregisterEntity(entity_id);

Querying

// Position
if (engine.getPosition(entity)) |pos| {
    draw(pos.x, pos.y);
}

// Current node
const node = engine.getCurrentNode(entity);

// Speed
const speed = engine.getSpeed(entity);
engine.setSpeed(entity, new_speed);

// Movement state
const moving = engine.isMoving(entity);

Pathfinding

Request Path

try engine.requestPath(entity, target_node);

Cancel Path

engine.cancelPath(entity);

Manual Position Update

// Teleport entity
engine.setPosition(entity, new_x, new_y);

Tick

Call every frame to update entity positions:

engine.tick(&game_context, delta_time);

This:

  1. Moves all entities along their paths
  2. Updates spatial indices
  3. Fires callbacks (node reached, path completed, path blocked)

API Reference

Method Description
init(allocator) Create engine (fallible)
deinit() Free resources
addNode(id, x, y) Add waypoint
addNodeAuto(x, y) Add with auto ID
addNodesFromPoints(points) Bulk add
removeNode(id) Remove waypoint
addEdge(from, to, bidirectional) Add connection
connectNodes(mode) Auto-connect
rebuildPaths() Recompute Floyd-Warshall
registerEntity(id, x, y, speed) Add entity
unregisterEntity(id) Remove entity
requestPath(entity, node) Start moving
cancelPath(entity) Stop moving
tick(ctx, delta) Update frame
getPosition(entity) Get x, y
setPosition(entity, x, y) Teleport
getSpeed(entity) Get speed
setSpeed(entity, speed) Set speed
isMoving(entity) Check if moving
getCurrentNode(entity) Get node ID
getNodeCount() Number of nodes
getEntityCount() Number of entities

Clone this wiki locally