AStar Implementation on Isometric Tilemap over Multiple Children

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Mango_05

Hello Godot Experts,

I am trying to use an AStar system to control ai in my game. I have managed to get this working for one sprite but since the AStar scripts are attached to the tilemap and the sprite is a child of that, when I try to add multiple sprites the script only moves the first one as it is called Player, and the others are Player2, Player3, etc.

Image Reference (Background is the one that holds the AStar scripts)

Is there any way I could access all children from the tilemap script and make them move too, without having to instance the tilemap as a child of the Player?

If any further information is required, please ask. Thank you

:bust_in_silhouette: Reply From: timothybrentwood

As the AStar node is implemented through the TileMap it can be responsible for path-finding any child or sibling node. Children of the TileMap have their position property in local space meaning it takes the TileMap’s origin into account.

Assuming the TileMap’s parent is positioned at (0,0), if your TileMap has its origin at (64,64), the formula for finding a child’s global position would be child_node.position + Vector2(64,64) *this is also calculated for you via the child_node.global_position property. However, a sibling of the TileMap at the exact same position would have its sibling_node.position == sibling_node.global_position because its parent (same as TileMap’s) has its origin at (0,0).

At some point in your code you have a function that takes in two positions and returns a path between them. I don’t know how you have your AStar node implemented but seeing as you’re using a TileMap you’re probably feeding it map coordinates. So your function looks something like this:

func find_path(world_start, world_end)
    var map_start = world_to_map(world_start)
    var map_end = world_to_map(world_end)
    var start_point_index = get_point_index(map_start)
    var end_point_index = get_point_index(map_end)

    var map_path = astar_node.get_point_path(start_point_index, end_point_index)
    var world_path = []
    for map_point in map_path:
         world_path.append(map_to_world(map_point.x, map_point.y))

    return world_path

The trick of it is to always call this function with the same kind of coordinates. Either coordinates that local to the TileMap, doing the conversion before you call the function - as in the example above - or global coordinates and take that into account when you’re calling it. TileMap.get_used_rect().position gets you the origin for your TileMap if you decide to go the global route.