Draw_line to center of tilemaplayer tile

Godot Version

4.3 stable

Question

I am working on a grid-based combat game, and one feature I want to have is the ability to draw a line from one tile to another. I’ve turned to draw_line in order to do this, since it seems the simplest way.

The intent is to have the player “jump” or “shoot” at a particular tile, and to draw a line on screen to indicate where the destination/target is. This seems like it ought to be a simple thing, but I’m stumped by a small issue.

Right now the I just have a very bare-bones project for the sake of keeping the experimentation simple. I have a Parent scene that contains a Node2D as the root with two children. One child is the TileMapLayer which contains the grid and the graphics. The other child is the Marker scene.

The Marker scene is similarly basic: it consists of a Node2D root with a Sprite2D child for the graphic.

Attached to the Marker Node2D is the following script:

extends Node2D

@onready var tile_map_layer: TileMapLayer = $“…/TileMapLayer”
@onready var marker: Node2D = $“.”

var mouse_pos
var mouse_tile
var line_start
var line_end
var grid_size = 16

func _ready() → void:
line_start = tile_map_layer.local_to_map(global_position)

func _process(delta: float) → void:
mouse_tile = tile_map_layer.local_to_map(to_local(get_global_mouse_position()))
mouse_pos = tile_map_layer.map_to_local(mouse_tile)
#line_end = mouse_pos
line_end = Vector2(
mouse_pos.x - (grid_size/2),
mouse_pos.y + (grid_size/2)
)
queue_redraw()

func _unhandled_input(event: InputEvent) → void:
if event.is_action_pressed(“move”):
#move marker to center of cell?
marker.position.x += line_end.x
marker.position.y += line_end.y
line_start = tile_map_layer.local_to_map(to_local(global_position))
print("mouse_tile: ",mouse_tile)
print("mouse_pos: ",mouse_pos)
print("line_start: ",line_start)
print("line_end: ",line_end)

func _draw():
if line_start == null || line_end == null:
return
draw_line(line_start, line_end, Color.YELLOW, 1.0, false)

The goal here is to have a line drawn from the center of the Marker sprite to the center of the tile under the mouse. When the player clicks the left mouse button, the Marker scene snaps to the tile under the mouse when the click happened.

Right now the code above… works? There’s some discrepancy going on with where the center of the tile is visually vs where the center of the tile is in terms of coordinates? When the mouse moves over the centerline of the tile, the line will snap to an adjacent tile rather than the one the mouse is hovering over. It’s like the visual tileset doesn’t line up with where the game thinks the line should terminate, and I’m unsure how to intuit a solution. You can see where I’m trying to offset the line_end by adding half the grid size, but that seems to be the problem in some way? But when I remove that Vector2 stuff and uncomment the line above, it breaks even more.

Anyway, I’m hoping someone can point out what I’m doing wrong, or even suggest another, simpler way to accomplish what I’m trying to do. Someone suggested using the Line2D node instead, but I’m not sure how that would fix whatever issue I’m running into here.

Thanks in advance!

Maybe you already found a solution yourself in the last few days, but just to be sure, here’s a solution:

calculate line_end like this:

	line_end = Vector2(
		floor(mouse_pos.x / grid_size) * grid_size,
		floor(mouse_pos.y / grid_size) * grid_size 
	)

also, make sure the marker is in the middle of a tile, you could for example add this to the _ready() function:

	# make sure marker is at the center of a tile
	marker.position = floor(marker.position / grid_size) * grid_size + Vector2(grid_size/2,grid_size/2)

and change mouse_tile to this:

	mouse_tile = tile_map_layer.local_to_map(to_local(get_global_mouse_position() + Vector2(grid_size/2,grid_size/2)))


Also, a little formatting advice for future posts: You can make code blocks using ``` like this:

```
some code
```