I have a grid layout with AStar2D, to which I added the visuals to show the path it will take.
It uses sprites from a png tileset of 4x4.
Both $GridTerrain and $GridArrow are tilemaps.
The good news is it works flawless.
However, as the code clearly shows, I gave up on a clever way to solve this, and simply brute forced everything in there.
How would you handle this?
Is this code to slow to run every frame?
Know of any tutorial or example code that will go in depth to grid based pathing?
extends Node2D
var cellSize = Vector2(64, 64)
var path: PoolVector2Array
#these directly relate to the spritesheet (4x4), with all arrow pathing possibilities
enum {PATH_CROSS, PATH_CENTER, PATH_WEST_EAST, PATH_SOUTH_NORTH,
PATH_START_NORTH, PATH_START_EAST, PATH_START_SOUTH, PATH_START_WEST,
PATH_NORTH_EAST, PATH_EAST_SOUTH, PATH_SOUTH_WEST, PATH_WEST_NORTH,
PATH_END_NORTH, PATH_END_EAST, PATH_END_SOUTH, PATH_END_WEST}
enum{NORTH, EAST, SOUTH, WEST}
func _process(delta):
var from = Vector2(7, 7) #just a random point to test the code
var to = worldToGrid(get_viewport().get_mouse_position())
path = $GridTerrain.getPath(from, to) #this gets a PoolVector2Array filled by AStar2D
drawPath()
func drawPath():
$GridArrow.clear()
if path.size() > 1: # is the path at least 2 segments long?
var count = 0
var lastCardinal = NORTH
for point in path:
if count == 0: #start of path
match cardinalNextCell(point, path[count + 1]):
NORTH:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_START_NORTH))
lastCardinal = SOUTH
EAST:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_START_EAST))
lastCardinal = WEST
SOUTH:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_START_SOUTH))
lastCardinal = NORTH
WEST:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_START_WEST))
lastCardinal = EAST
elif count < path.size() - 1: #before the end point?
var nextCardinal = cardinalNextCell(point, path[count + 1])
match lastCardinal:
NORTH:
if nextCardinal == SOUTH:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_SOUTH_NORTH))
elif nextCardinal == WEST:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_WEST_NORTH))
lastCardinal = EAST
else:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_NORTH_EAST))
lastCardinal = WEST
EAST:
if nextCardinal == WEST:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_WEST_EAST))
elif nextCardinal == SOUTH:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_EAST_SOUTH))
lastCardinal = NORTH
else:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_NORTH_EAST))
lastCardinal = SOUTH
SOUTH:
if nextCardinal == NORTH:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_SOUTH_NORTH))
elif nextCardinal == EAST:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_EAST_SOUTH))
lastCardinal = WEST
else:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_SOUTH_WEST))
lastCardinal = EAST
WEST:
if nextCardinal == EAST:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_WEST_EAST))
elif nextCardinal == SOUTH:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_SOUTH_WEST))
lastCardinal = NORTH
else:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_WEST_NORTH))
lastCardinal = SOUTH
else: #the end point
match lastCardinal:
NORTH:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_END_SOUTH))
EAST:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_END_WEST))
SOUTH:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_END_NORTH))
WEST:
$GridArrow.set_cell(point.x, point.y, 0, false, false, false, getPathTile(PATH_END_EAST))
count += 1
func worldToGrid(target: Vector2) -> Vector2:
var newCoord = Vector2.ZERO
newCoord.x = floor(target.x / cellSize.x)
newCoord.y = floor(target.y / cellSize.y)
return newCoord
func gridToWorld(target: Vector2) -> Vector2:
var newCoord = Vector2.ZERO
newCoord.x *= cellSize.x
newCoord.y *= cellSize.y
return newCoord
func getPathTile(target: int) -> Vector2: #subtile from pathing tileset
return Vector2((target % 4), floor(target / 4))
func cardinalNextCell(current: Vector2, next: Vector2) -> int:
if current.x > next.x:
return WEST
elif current.x < next.x:
return EAST
elif current.y > next.y:
return NORTH
else:
return SOUTH