Excellent diagram, it really explains the path - I wanted this behavior as well, and ended up writing code to get a list of tiles overlapping an Area2D. Right now this only covers rectangles, but it could be extended to other shapes.
class_name TileDetector
extends Area2D
func _on_TileDetector_body_entered(body):
if body is TileMap:
if body.get_parent().has_method("add_active_body"):
body.get_parent().add_active_body(self)
# bug/strange behavior:
# area2ds fire body_exited when tilemap set_cell is called
# https://github.com/godotengine/godot/issues/61220
# func _on_TileDetector_body_exited(body:Node):
# if body is TileMap:
# if body.get_parent().has_method("remove_active_body"):
# body.get_parent().remove_active_body(self)
# Returns an array of vector2s (the overlapping tilemap cell coords)
func overlapping_cells(tm: TileMap) -> Array:
# TODO may need to support more shapes here
var extents = $CollisionShape2D.shape.extents
var first_cell = tm.world_to_map(global_position - extents)
var last_cell = tm.world_to_map(global_position + extents)
var cells = []
for x in range(first_cell.x, last_cell.x + 1):
for y in range(first_cell.y, last_cell.y + 1):
cells.append(Vector2(x, y))
return cells
I then hold a reference to the area2d on the tilemap, and call this from the tilemap’s _process method… not ideal, but works for my use-case - maybe there’s some better way to do this?