A modular, highly decoupled pathfinding and agent management system built in GameMaker.
This system solves the complex problem of mixing strict grid-based environments (like factory builders or colony sims) with fluid, multi-unit swarm movement (like traditional RTS games).
- Dual-Mode Architecture: *
ROUTEMode: Strict matrix reservation. Agents lock tiles ahead of them, wait in traffic, and prevent overlaps. Ideal for factory logistics and predictable NPC routines.RTSMode: Fluid movement. Agents decouple from the grid matrix during travel, using pixel-perfect path following and soft collisions, anchoring back to the grid only upon arrival.
- Ulam Spiral Formations: Dynamically calculates valid, non-overlapping destination tiles for multiple agents around a single target click.
- Swarm Flow (Boids): Uses separation vectors to push agents away from each other during RTS travel. This prevents the classic A* "single-file funneling" effect when rounding corners.
- Waypoint Relaxation: Agents take smoother, wider turns at intermediate waypoints to maintain swarm cohesion without fighting for the exact same pixel.
The system is split into five main components, making it entirely plug-and-play for your existing project:
Holds global.matrix (a 2D array representing the physical occupation of the room) and handles the request_reservation and free_reservation functions. This ensures two agents can never legally occupy the same final tile.
Handles box-selection (Shift + Click) and raycasting. When ordering multiple units, it generates a mathematical spiral outward from the click, checks mp_grid for walls/obstacles, and assigns the closest available parking spot to each selected agent.
A Finite State Machine (IDLE, MOVING, WAITING) powered by a Belief-Desire-Intention (BDI) queue.
- Navigation: It uses GameMaker's native
mp_grid_pathto generate a macro-route (avoiding walls) but extracts the exact pixel coordinates to travel smoothly. - Rendering: Features built-in Y-Sorting (
depth = -bbox_bottom) and visual offsets so sprites can be adjusted without breaking the physical A* collision center.
Acts as a physical waypoint and route compiler on the map.
It let's the user create paths by clicking on it and drawing arrows.
When an agent stop over this object (enters the IDLE state), it automatically downloads the route into its intention queue and begins executing it step-by-step.
A smart, plug-and-play parent object for buildings, trees, and walls.
- Auto-Sizing: It automatically calculates its own grid footprint based on its
tiled_size_xandtiled_size_yvariables. - Auto-Registration: It registers itself into both
global.matrixandmp_gridupon creation, and cleanly frees those cells if it is destroyed.
- Select Agents: Hold
Shift+Left Click & Dragto create a selection box around multiple agents. - Cancel Selection: Hold
Shift+Left Clickto clear your current selection. - Move Agents: With agents selected, click on the map to issue a move command. They will automatically calculate a path and form around the target using the Ulam Spiral logic.
- Create a Route:
Left Clickon anobj_route_starter(Router) to begin placing directional arrows and drawing a path on the grid. - Confirm Route: Press
Enterto compile and save the route. Any agent that stops over this Router will now automatically follow the established path.
- Initialize the system by calling the
Start_world()function (just put theobj_start_worldin your room). Make sure this runs first in your execution order (this function automatically creates theobj_input_manager,obj_grid_managerand sets up the environment). - Ensure your room's floor tiles align perfectly with
global.tile_size. - Create static colliders by assigning
obj_Obstacleas the parent to your environment sprites. Be sure to set theirtiled_size_xandtiled_size_yvariables to match the sprite's dimensions. - Place
obj_route_starterobjects on the map to define automated paths. - Drop your
obj_agentinstances into the room. - Have fun!
This project is open-source. If you find ways to optimize the vector math, improve the Boids alignment/cohesion, or add new mechanics, please feel free to contribute to the repo.
Let's build something cool together!