Skip to content

Map sources

Both nav backends share the same constructor signatures, so you can wire up a grid from Tiled, LDtk, or any custom data source with the same call regardless of which backend you choose.

NewFromTiledLayer accepts the raw fields of a parsed Tiled layer. Pass Map.Width, Map.Height, Map.TileWidth, Map.TileHeight, and Layer.Data (GID slice, row-major). The blocked function returns true for GIDs that should be treated as impassable; GID 0 (empty cell) is always impassable regardless:

layer := tiledMap.LayerByName("Walkable")
nav, err := navpathing.NewFromTiledLayer(
tiledMap.Width, tiledMap.Height,
tiledMap.TileWidth, tiledMap.TileHeight,
layer.Data,
func(gid int) bool { return gid == wallGID },
)

The kelindar backend uses the same signature—swap the package prefix to switch.

NewFromLDtkIntGrid accepts an LDtk IntGrid layer. Pass LayerInstance.CellsWide, CellsHigh, GridSize, the level’s WorldX/WorldY as origin, and IntGridCSV. The blocked function returns true for IntGrid values that are impassable; value 0 (empty) is always impassable:

layer := level.LayerByIdentifier("Collision")
nav, err := navpathing.NewFromLDtkIntGrid(
layer.CellsWide, layer.CellsHigh, layer.GridSize,
float64(level.WorldX), float64(level.WorldY),
layer.IntGridCSV,
func(val int) bool { return val == 1 }, // 1 = solid wall
)

The originX/originY arguments handle multi-level LDtk projects where levels are positioned at non-zero world coordinates.

Use New with a GridConfig to build a grid from any walkability function.

For the pathing backend, provide a Walkable predicate:

nav, err := navpathing.New(navpathing.GridConfig{
Cols: mapWidth, Rows: mapHeight,
CellW: cellSize, CellH: cellSize,
Walkable: func(col, row int) bool {
return myMap.IsWalkable(col, row)
},
})

For the kelindar backend, provide a CostOf function. A cost of 0 means impassable; higher values are traversal costs that A* minimises—useful for terrain variety:

nav, err := navkelindar.New(navkelindar.GridConfig{
Cols: mapWidth, Rows: mapHeight,
CellW: cellSize, CellH: cellSize,
CostOf: func(col, row int) uint16 {
switch myMap.TerrainAt(col, row) {
case TerrainWall: return 0 // impassable
case TerrainRoad: return 1
case TerrainGrass: return 2
case TerrainSwamp: return 5
}
return 1
},
})

A* will prefer lower-cost paths—an NPC routes through a road rather than swamp when both reach the goal.

See also: Backends & wiring, kelindar backend.