A* PATHING

EasyStar.js + AngularJS Demo · MMO Combat Lab

What this demonstrates

Every entity in the MMO Combat Lab simulation occupies a position on a 32x32 grid. Each engine tick is 0.1 seconds. At a base movement speed of 6.4 m/s, an entity moves 0.64 meters per tick. With 2-meter grid squares, that works out to 3 ticks per orthogonal step and 5 ticks per diagonal step, the values you'll see demonstrated here.

To navigate around obstacles, the simulation uses a pathfinding algorithm called A* (A-star). Given a start point, an end point, and a map of walkable versus blocked cells, A* finds the shortest valid path between them. This is the same algorithm used in commercial video games, GPS navigation, and robotics.

One implementation detail worth understanding: A* can be run synchronously (calculate the entire path immediately) or asynchronously (spread the work across multiple frames and fire a callback when ready). For a visual game, async keeps the screen responsive. For a headless simulation running 10,000 iterations as fast as possible, sync is the right choice. The path is available the same tick it is requested. The toggle below lets you observe both modes on the same grid.

01
Left-click any open cell to pathfind there; watch A* route around walls
02
Right-click to place or remove walls; paths recalculate automatically
03
Movement is tick-based: 3 ticks per square at 100ms each = 300ms per step
04
Toggle sync vs async to see how calculation timing affects pathfinding behavior
Grid · {{grid.length}}×{{grid[0].length}}
Mode: {{syncMode ? 'SYNC' : 'ASYNC'}}
Player (P)
Goal (✕)
Wall
Path
Left click: move here  ·  Right click: toggle wall
Movement speed: 3 ticks × 100ms = 300ms/square
Matches the spec: orthogonal = 3 ticks, diagonal = 5 ticks.
In the sim, 1 tick = 0.1s → 0.3s per square = 0.64 m/tick.

Entity State

Player position ({{playerPos.x}}, {{playerPos.y}})
Goal position ({{goalPos.x}}, {{goalPos.y}})
Path length {{currentPath.length > 0 ? currentPath.length + ' squares' : '—'}}
Steps taken {{stepCount}}
Moving YES NO
EasyStar mode {{syncMode ? 'Sync' : 'Async'}}

Event Log

{{entry.t}} {{entry.msg}}
Waiting for input...