Repository navigation
Spatial Queries
Alexandre Mondaini Calvão edited this page Dec 3, 2025
·
1 revision
The PathfindingEngine includes a QuadTree-based spatial index for efficient O(log n) queries. This is useful for combat systems, AI awareness, and finding nearby objects.
Two separate QuadTrees are maintained:
- Node spatial index - For finding nearby waypoints
- Entity spatial index - For finding nearby entities
Both are automatically updated as entities move.
var buffer: [64]u64 = undefined;
const nearby = engine.getEntitiesInRadius(center_x, center_y, radius, &buffer);
for (nearby) |entity_id| {
// Process each nearby entity
}Use cases:
- Attack range detection
- Explosion damage
- AI awareness radius
- Proximity triggers
var buffer: [64]u64 = undefined;
const in_area = engine.getEntitiesInRect(x, y, width, height, &buffer);
for (in_area) |entity_id| {
// Process each entity in rectangle
}Use cases:
- Room detection
- Zone triggers
- Selection boxes
- Camera culling
var buffer: [32]u32 = undefined;
const nearby_nodes = engine.getNodesInRadius(x, y, radius, &buffer);
for (nearby_nodes) |node_id| {
// Process each nearby node
}Use cases:
- Finding spawn points
- Patrol waypoints
- Cover positions
var buffer: [16]u64 = undefined;
const at_node = engine.getEntitiesAtNode(node_id, &buffer);
for (at_node) |entity_id| {
// Entity is at this waypoint
}Use cases:
- Checking if node is occupied
- Triggering node-based events
fn attackNearbyEnemies(engine: *Engine, game: *Game, attacker: u64, damage: u32) void {
const pos = engine.getPosition(attacker) orelse return;
const attack_range: f32 = 50.0;
var nearby: [32]u64 = undefined;
const targets = engine.getEntitiesInRadius(pos.x, pos.y, attack_range, &nearby);
for (targets) |target| {
if (target == attacker) continue; // Don't hit self
if (game.isEnemy(target)) {
game.applyDamage(target, damage);
}
}
}fn updateAI(engine: *Engine, game: *Game, enemy: u64) void {
const pos = engine.getPosition(enemy) orelse return;
const sight_range: f32 = 200.0;
var nearby: [64]u64 = undefined;
const visible = engine.getEntitiesInRadius(pos.x, pos.y, sight_range, &nearby);
for (visible) |entity| {
if (game.isPlayer(entity)) {
// Player spotted! Chase them
if (engine.getCurrentNode(entity)) |player_node| {
engine.requestPath(enemy, player_node) catch {};
}
break;
}
}
}The QuadTree provides O(log n) average-case performance for spatial queries, compared to O(n) for brute-force distance checks.
| Operation | QuadTree | Brute Force |
|---|---|---|
| Radius query | O(log n + k) | O(n) |
| Rectangle query | O(log n + k) | O(n) |
Where n is total entities and k is result count.
All query methods write to a caller-provided buffer. Size the buffer appropriately:
// Small area, few expected results
var small_buffer: [8]u64 = undefined;
// Large area, many possible results
var large_buffer: [256]u64 = undefined;If more entities exist than buffer size, only the first buffer.len are returned.
Entity positions in the spatial index are automatically updated during tick(). No manual update is needed.
// Movement updates spatial index automatically
engine.tick(&game, delta);
// Queries reflect current positions
const nearby = engine.getEntitiesInRadius(x, y, r, &buffer);