pathfind_astar.gd 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. extends TileMap
  2. enum Tile {
  3. OBSTACLE,
  4. START_POINT,
  5. END_POINT,
  6. }
  7. const CELL_SIZE = Vector2i(64, 64)
  8. const BASE_LINE_WIDTH: float = 3.0
  9. const DRAW_COLOR = Color.WHITE * Color(1, 1, 1, 0.5)
  10. # The object for pathfinding on 2D grids.
  11. var _astar := AStarGrid2D.new()
  12. var _start_point := Vector2i()
  13. var _end_point := Vector2i()
  14. var _path := PackedVector2Array()
  15. func _ready() -> void:
  16. # Region should match the size of the playable area plus one (in tiles).
  17. # In this demo, the playable area is 17×9 tiles, so the rect size is 18×10.
  18. _astar.region = Rect2i(0, 0, 18, 10)
  19. _astar.cell_size = CELL_SIZE
  20. _astar.offset = CELL_SIZE * 0.5
  21. _astar.default_compute_heuristic = AStarGrid2D.HEURISTIC_MANHATTAN
  22. _astar.default_estimate_heuristic = AStarGrid2D.HEURISTIC_MANHATTAN
  23. _astar.diagonal_mode = AStarGrid2D.DIAGONAL_MODE_NEVER
  24. _astar.update()
  25. for i in range(_astar.region.position.x, _astar.region.end.x):
  26. for j in range(_astar.region.position.y, _astar.region.end.y):
  27. var pos := Vector2i(i, j)
  28. if get_cell_source_id(0, pos) == Tile.OBSTACLE:
  29. _astar.set_point_solid(pos)
  30. func _draw() -> void:
  31. if _path.is_empty():
  32. return
  33. var last_point: Vector2 = _path[0]
  34. for index in range(1, len(_path)):
  35. var current_point: Vector2 = _path[index]
  36. draw_line(last_point, current_point, DRAW_COLOR, BASE_LINE_WIDTH, true)
  37. draw_circle(current_point, BASE_LINE_WIDTH * 2.0, DRAW_COLOR)
  38. last_point = current_point
  39. func round_local_position(local_position: Vector2i) -> Vector2i:
  40. return map_to_local(local_to_map(local_position))
  41. func is_point_walkable(local_position: Vector2) -> bool:
  42. var map_position: Vector2i = local_to_map(local_position)
  43. if _astar.is_in_boundsv(map_position):
  44. return not _astar.is_point_solid(map_position)
  45. return false
  46. func clear_path() -> void:
  47. if not _path.is_empty():
  48. _path.clear()
  49. erase_cell(0, _start_point)
  50. erase_cell(0, _end_point)
  51. # Queue redraw to clear the lines and circles.
  52. queue_redraw()
  53. func find_path(local_start_point: Vector2i, local_end_point: Vector2i) -> PackedVector2Array:
  54. clear_path()
  55. _start_point = local_to_map(local_start_point)
  56. _end_point = local_to_map(local_end_point)
  57. _path = _astar.get_point_path(_start_point, _end_point)
  58. if not _path.is_empty():
  59. set_cell(0, _start_point, 0, Vector2i(Tile.START_POINT, 0))
  60. set_cell(0, _end_point, 0, Vector2i(Tile.END_POINT, 0))
  61. # Redraw the lines and circles from the start to the end point.
  62. queue_redraw()
  63. return _path.duplicate()