Hi everyone I am working with Godot 4.3 and struggling with the new tile system while trying to "highlight" a tile when hovered over with the cursor. I want to replace a cell's visual appearance without actually removing or replacing the cell data.
I've used the following function to manipulate tiles:
void set_cell(int layer, Vector2i coords, int source_id = -1, Vector2i atlas_coords = Vector2i(-1, -1), int alternative_tile = 0)
However, my implementation seems to remove the cell instead of just highlighting it. Here's the relevant part of my code:
extends TileMap
var highlighted_tile_position: Vector2i = Vector2i(-1, -1)
var highlight_tile_id:Vector2i = get_cell_atlas_coords(layer, Vector2i(0, 1)) # Ensure this is a valid and visible tile ID
func _process(delta: float):
var mouse_pos = to_local(get_global_mouse_position())
var tile_pos = local_to_map(mouse_pos)
if tile_pos != highlighted_tile_position:
# Reset the previously highlighted tile if valid
if highlighted_tile_position != Vector2i(-1, -1) and get_cell_source_id(layer, highlighted_tile_position) != -1:
set_cell(layer, highlighted_tile_position, get_cell_source_id(layer, highlighted_tile_position)) # Reset to its original ID
# Highlight the new tile if valid
if get_cell_source_id(layer, tile_pos) != -1:
highlighted_tile_position = tile_pos
set_cell(layer, tile_pos, 0, highlight_tile_id) # Attempt to highlight new tile
The issue seems to be in the way I'm using set_cell as it erases the tile instead of highlighting it. I suspect my source_id, atlas_coords, and alternative_tile parameters might be incorrect.
Questions:
How do I correctly set these parameters to change the tile's appearance without removing the underlying data? Is there a more appropriate way to temporarily alter a tile's appearance on hover? Any insights or examples would be greatly appreciated.
Hi everyone I am working with Godot 4.3 and struggling with the new tile system while trying to "highlight" a tile when hovered over with the cursor. I want to replace a cell's visual appearance without actually removing or replacing the cell data.
I've used the following function to manipulate tiles:
void set_cell(int layer, Vector2i coords, int source_id = -1, Vector2i atlas_coords = Vector2i(-1, -1), int alternative_tile = 0)
However, my implementation seems to remove the cell instead of just highlighting it. Here's the relevant part of my code:
extends TileMap
var highlighted_tile_position: Vector2i = Vector2i(-1, -1)
var highlight_tile_id:Vector2i = get_cell_atlas_coords(layer, Vector2i(0, 1)) # Ensure this is a valid and visible tile ID
func _process(delta: float):
var mouse_pos = to_local(get_global_mouse_position())
var tile_pos = local_to_map(mouse_pos)
if tile_pos != highlighted_tile_position:
# Reset the previously highlighted tile if valid
if highlighted_tile_position != Vector2i(-1, -1) and get_cell_source_id(layer, highlighted_tile_position) != -1:
set_cell(layer, highlighted_tile_position, get_cell_source_id(layer, highlighted_tile_position)) # Reset to its original ID
# Highlight the new tile if valid
if get_cell_source_id(layer, tile_pos) != -1:
highlighted_tile_position = tile_pos
set_cell(layer, tile_pos, 0, highlight_tile_id) # Attempt to highlight new tile
The issue seems to be in the way I'm using set_cell as it erases the tile instead of highlighting it. I suspect my source_id, atlas_coords, and alternative_tile parameters might be incorrect.
Questions:
How do I correctly set these parameters to change the tile's appearance without removing the underlying data? Is there a more appropriate way to temporarily alter a tile's appearance on hover? Any insights or examples would be greatly appreciated.
Share Improve this question asked Jan 19 at 17:36 DanielLDanielL 2381 silver badge9 bronze badges 1- 1 You can check the source Id and atlas coords by hovering over the tile you want to use in the tilemap tab of the editor. This should be the first thing you should check. – Bugfish Commented Jan 20 at 16:48
1 Answer
Reset to default 1Setting cells via set_cell()
works best when you want your terrain to change dynamically at runtime in response to in-game events (such as explosions altering the game field) because the engine uses the data stored for each tile for auto-tiling, collisions, and physics interaction.
On the other hand, a marker that highlights tiles where the mouse cursor is only serves visual purposes; it doesn't belong to the tilemap entity but to the user interface domain.
Since you want to preserve underlying tile data, I strongly recommend treating such marker as a separate, independent Node. This way, you can control its behaviour, change its appearance, animate it, and much more.
I propose a solution where your TileMap
(or TileMapLayer
, the actual "new tile system") controls a child Node acting as a highlight marker and following the mouse cursor while snapping to the tilemap grid:
extends TileMap
@onready var marker: Node2D = get_node("Marker") # Child Node2D
func _process(delta: float):
var mouse_pos = get_local_mouse_position()
var cell_pos = local_to_map(mouse_pos)
highlight_cell(cell_pos)
func highlight_cell(cell_position: Vector2i):
marker.position = map_to_local(cell_position)
The marker Node can be anything you want: Sprite2D
, AnimatedSprite2D
, or even a plain Node2D
with some custom drawing such as:
extends Node2D
@export var size := Vector2.ONE * 14.0
@export var color := Color(1.0, 1.0, 0.0, 0.5)
func _draw():
draw_rect(Rect2(-size / 2.0, size), color)
Here's the result (tileset credits: Happyland by Buch on OGA):