godot-demo-projects/2d/navigation_astar/pathfind_astar.gd

85 lines
2.4 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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()