extends TileMap enum Tile { OBSTACLE, START_POINT, END_POINT, } const CELL_SIZE = Vector2i(64, 64) const BASE_LINE_WIDTH: float = 3.0 const DRAW_COLOR = Color.WHITE * Color(1, 1, 1, 0.5) # The object for pathfinding on 2D grids. var _astar := AStarGrid2D.new() var _start_point := Vector2i() var _end_point := Vector2i() var _path := PackedVector2Array() func _ready() -> void: # Region should match the size of the playable area plus one (in tiles). # In this demo, the playable area is 17×9 tiles, so the rect size is 18×10. _astar.region = Rect2i(0, 0, 18, 10) _astar.cell_size = CELL_SIZE _astar.offset = CELL_SIZE * 0.5 _astar.default_compute_heuristic = AStarGrid2D.HEURISTIC_MANHATTAN _astar.default_estimate_heuristic = AStarGrid2D.HEURISTIC_MANHATTAN _astar.diagonal_mode = AStarGrid2D.DIAGONAL_MODE_NEVER _astar.update() for i in range(_astar.region.position.x, _astar.region.end.x): for j in range(_astar.region.position.y, _astar.region.end.y): var pos := Vector2i(i, j) if get_cell_source_id(0, pos) == Tile.OBSTACLE: _astar.set_point_solid(pos) func _draw() -> void: if _path.is_empty(): return var last_point: Vector2 = _path[0] for index in range(1, len(_path)): var current_point: Vector2 = _path[index] draw_line(last_point, current_point, DRAW_COLOR, BASE_LINE_WIDTH, true) draw_circle(current_point, BASE_LINE_WIDTH * 2.0, DRAW_COLOR) last_point = current_point func round_local_position(local_position: Vector2i) -> Vector2i: return map_to_local(local_to_map(local_position)) func is_point_walkable(local_position: Vector2) -> bool: var map_position: Vector2i = local_to_map(local_position) if _astar.is_in_boundsv(map_position): return not _astar.is_point_solid(map_position) return false func clear_path() -> void: if not _path.is_empty(): _path.clear() erase_cell(0, _start_point) erase_cell(0, _end_point) # Queue redraw to clear the lines and circles. queue_redraw() func find_path(local_start_point: Vector2i, local_end_point: Vector2i) -> PackedVector2Array: clear_path() _start_point = local_to_map(local_start_point) _end_point = local_to_map(local_end_point) _path = _astar.get_point_path(_start_point, _end_point) if not _path.is_empty(): set_cell(0, _start_point, 0, Vector2i(Tile.START_POINT, 0)) set_cell(0, _end_point, 0, Vector2i(Tile.END_POINT, 0)) # Redraw the lines and circles from the start to the end point. queue_redraw() return _path.duplicate()