Getting lost in coordinate translations

Godot Version

4.3

Question

I am trying to do tile based movement, but by mouseclick in a 2d world. So you click a tile, on release, the character moves one tile per tick till we get to the clicked tile.
All good.
I have a giant map. and a player.
To not have to load in the entire map, I figured I would use AStarGrid2D and just add it to my player script.
I would then simply only load the current VisibleRect() into the A* to limit the amount of computation needed.

However, I’m getting lost in trying to figure out which coordinates go where.

Here is my code.

public override void _Ready()
	{
		_sprite = GetNode<AnimatedSprite2D>("AnimatedSprite2D");
		_map = GetParent().GetNode<TileMapLayer>("Map");
		_tileSize = _map.TileSet.TileSize;
		_aStar = new AStarGrid2D();
		
		_sprite.Play("Idle Down");

		_aStar.DiagonalMode = AStarGrid2D.DiagonalModeEnum.OnlyIfNoObstacles;
		_aStar.DefaultComputeHeuristic = AStarGrid2D.Heuristic.Manhattan;
		_aStar.CellSize = _tileSize;
	}

	private void initializeAStar()
	{
		_aStar.Clear();
		var visibleRect = (Rect2I)GetViewport().GetVisibleRect();
		_aStar.Region = visibleRect;
		if (_aStar.IsDirty())
		{
			_aStar.Update();
		}
	}

	public override void _Input(InputEvent @event)
	{
		if (@event is InputEventMouseButton mouseEvent && @event.IsActionReleased("click"))
		{
			var clickedTile = mouseEvent.Position;
			CalculatePath(clickedTile);
		}
	}

	public override void _PhysicsProcess(double delta)
	{
		if (_path != null && _currentPathIndex < _path.Count())
		{
			GlobalPosition = _path[_currentPathIndex] * _tileSize;
			_currentPathIndex++;
		}
	}

	private void CalculatePath(Vector2 targetTile)
	{
		var playerPosition = _map.LocalToMap(Position);
		var targetPosition = _map.LocalToMap(targetTile);
		initializeAStar();

		_path = _aStar.GetIdPath(playerPosition, targetPosition, true);
		_currentPathIndex = 0;
	}

I reckon it goes wrong in converting between viewport coordinates, and local coordinates. - can someone make it make sense please? :sweat_smile:.

ViewPort.GetVisibleRect() gives me global coordinates.
MousePosition gives me local.
Position gives me local.
Also I really want the player to snap to the tiles why i figured I have to get the tilemap coordinates in there somewhere.

My scene layout looks like this

|- World (tilemap)
|- Player (astargrid2d here)
   |- Camera

Would it make my life ALOT easier to simply have the a* in a world script and reference it from the player to move?

Thanks in advance.

Have you confirmed that mouseEvent.Position is actually returning the position of the mouse local to the player?

If so, to turn it into global coordinates, you just add it to the player position. To get it to snap, you need to round it to the nearest tile size (plus half a tile size I think, can’t remember).

I suspect that you are getting screen coordinates from your input event. So you may want to use get_global_mouse_position() instead if so.