TowerGame/scripts/tower_navigation_agent.gd

57 lines
1.8 KiB
GDScript3
Raw Normal View History

2025-06-10 13:34:26 +01:00
extends Node3D
class_name TowerNavigationAgent
# How close do we want to get to the target before finishing navigation
@export var target_distance: float = 2.0
# How close do we need to get to path points before advancing to the next one
@export var next_position_distance: float = 2.0
# How far can we get from the path before giving up and recalculating
@export var recalculate_distance: float = 5.0
var navigation_grid: NavigationGrid
var target_position: Vector3
var last_target_position: Vector3
var path : PackedVector3Array = []
var next_point_idx: int = 0
var grid: NavigationGrid
func _ready() -> void:
var node: Node = self
while !node is NavigationGrid and node.get_parent() != null:
node = node.get_parent()
grid = node as NavigationGrid
func get_next_path_position() -> Vector3:
if _ensure_path():
if global_position.distance_to(path[next_point_idx]) <= next_position_distance:
next_point_idx = min(next_point_idx+1, path.size()-1)
return path[next_point_idx]
else:
return Vector3()
func get_movement_direction() -> Vector3:
return get_next_path_position() - global_position
func is_target_reachable() -> bool:
return _ensure_path()
func is_navigation_finished() -> bool:
_ensure_path()
return path.is_empty()
func _ensure_path() -> bool:
if target_position.is_zero_approx():
return false
var recalculate_needed: bool = path.is_empty() \
or target_position.distance_to(last_target_position) >= target_distance \
or global_position.distance_to(path[next_point_idx]) >= recalculate_distance
if recalculate_needed:
var start_pos: int = grid.grid.get_closest_point(global_position)
var end_pos: int = grid.grid.get_closest_point(target_position)
path = grid.grid.get_point_path(start_pos, end_pos)
next_point_idx = 0
return !path.is_empty()
return true