Files
godot-demo-projects/2d/navigation_astar/pathfind_astar.gd
A Thousand Ships 0343cedd48 General proofreading (#1262)
* General proofreading for grammar and spelling
* General formatting
* Addition of appropriate literals where appropriate, i.e. `&"foo"` for `StringName` cases and `^"foo/bar"` for `NodePath` cases
2025-10-11 01:39:59 -07:00

90 lines
2.8 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 TileMapLayer
# Atlas coordinates in tile set for start/end tiles.
const TILE_START_POINT = Vector2i(1, 0)
const TILE_END_POINT = Vector2i(2, 0)
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.
# Depending on the setup, TileMapLayer's get_used_rect() can also be used.
_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()
# Iterate over all cells on the tile map layer and mark them as
# non-passable.
for pos in get_used_cells():
_astar.set_point_solid(pos)
# To skip cells with certain atlas coordinates you can use:
# if get_cell_atlas_coords(pos) == Vector2i(42, 23):
# ...
# You can also add a "Custom Data Layer" to the tile set to group
# tiles and check it here; in the following example using a string:
# if get_cell_tile_data(pos).get_custom_data("type") == "obstacle":
# ...
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(_start_point)
erase_cell(_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(_start_point, 0, TILE_START_POINT)
set_cell(_end_point, 0, TILE_END_POINT)
# Redraw the lines and circles from the start to the end point.
queue_redraw()
return _path.duplicate()