0 votes

Hi Folks,

I'm designing a simple map navigation system for a game which is based on clickable locations. Basically, you have a map, some locations within the map and a path between locations. Assuming the player cursor is on location A, you click on location B and it will move the cursor through the path until it arrives at location B. Furthermore, since the map is designed as a TileMap, I wanted to limit the movement to cells (so it is a grid movement).

I created a new map scene with the following organization:

Imgur

The reason I put Navigation2D under TileMap and define a Polygon for it (instead of using the polygons from the tileset within the tilemap) is that I sort of need to limit the size of the polygon within each cell of the TileMap to make grid movement easier.

An example instance of this scene is as below

Imgur

Each instance will have several locations defined (the YSorts are all specific location scenes that inherit from a base Location scene). The way this looks is as below

Imgur

I hid some objects from the scene to make it easier to see. I left two locations, City and Ruins, and as a test, I was charting the path between the City and the Ruins. If I have the Map transform at (0, 0), it works perfectly, see below:

Imgur

Each round sprite is a tile within the tilemap. I'm also displaying the navigation polygon, and red crosses are debug sprites I generate at each position of the path, in addition to the line of the path. My procedure to generate the grid movement path is to, given the path between the current position and the destination position, for each position in the path I calculate the tilemap position, then recalculate the world (local position), and then center the location position by adding half the tile size to each local position within the path. The code is as below:

A signal handler responds to a signal from each children location when it is clicked within a region around it, receiving the local position of the location; currenttilemapposition stores the cursor position in the tilemap. There is bunch of debug code which I'll show the output for after the explanation. Here is the signal handler:

func _on_location_selected(location_position) -> void:

var current_position = map_to_world(current_tilemap_position)
current_position = compute_position_centered_on_tile(current_position)
var location_tilemap_position = world_to_map(location_position)

print("Navigation: ")
print("    -> From: {0}: {1} | global: {2}".format({"0":current_tilemap_position, "1":current_position, "2":to_global(current_position)}))
print("    -> To: {0}: {1} | global: {2}".format({"0":location_tilemap_position, "1":location_position, "2":to_global(location_position)}))

var raw_path = nav_2d.get_simple_path(current_position, location_position)
print("    -> raw_path: ", raw_path)


if raw_path:
    var path = compute_centered_path(raw_path)
    print("    -> centered_path: ", path)

    current_tilemap_position = location_tilemap_position
    myline2d.points = path
    myline2d.width = 3

    for pos in path:
        gen_debug_sprite(pos)

The other two functions are:

func compute_position_centered_on_tile(pos: Vector2) -> Vector2:

pos.x += cell_size.x/2
pos.y += cell_size.y/2

return pos

func compute_centered_path(path: PoolVector2Array) -> PoolVector2Array:

var centered_path: PoolVector2Array = []

for pos in path:

    var centered_pos = map_to_world(world_to_map(pos))
    centered_pos = compute_position_centered_on_tile(centered_pos)

    centered_path.append(centered_pos)  

return centered_path

This works fine when the position of Map is at (0, 0), with the output below:

Imgur

However, since I'm dealing with local position (on both maptoworld and getsimplepath) I wanted to test what happens when I move the Map to not be at (0, 0). It totally broke my paths! This is the result when Map is at (50, 50)

Imgur

and the output is:

Imgur

Now the weird thing is, even though get_simple_path is getting as input the positions (528, 240) and (1296, 176), its output starts at (570, 240) and goes to (1338, 218). I can't figure it out what is happening here, since per the documentation, get_simple_path should operate over local paths, so the output should be fine. Furthermore, this dislocation seens to be proportional to how much I moved Map, since for moves less than (10, 10) the output is still correct. Can you folks help me here?

Godot version v3.5.stable.official [991bb6ac7]
in Engine by (12 points)

1 Answer

0 votes

There is a warning on your Navigation2D node. With Godot 3.5+ the old Navigation2D is deprecated. It now no longer functions like the old documentation would state as it has not been updated since. The old pre 3.5 navigation did local pathfinding on the node while the new navigation uses the global Navigation2DServer which expects global positions on the functions. For some compatibility the old Navigation2D function getsimplepath() forwards to Navigation2DServer.mapgetpath() but there is no local to global auto-conversion.

ago by (86 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.