pathfind_astar.gd 2.3 KB

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