1use crate::avoid::{resolve, AvoidanceConfig, Neighbor2};
5use crate::vec::NavVec;
6
7#[derive(Clone, Copy, Debug)]
9pub struct AgentNeighbor<V> {
10 pub position: V,
12 pub velocity: V,
14 pub radius: f32,
16}
17
18#[derive(Clone, Debug)]
25pub struct NavigationAgent<V: NavVec> {
26 pub path: Vec<V>,
28 pub waypoint: usize,
30 pub max_speed: f32,
32 pub arrival_radius: f32,
34 pub waypoint_advance: f32,
36 pub desired_velocity: V,
38 pub avoidance: AvoidanceConfig,
40 pub avoidance_enabled: bool,
42}
43
44impl<V: NavVec> NavigationAgent<V> {
45 pub fn new(max_speed: f32) -> Self {
47 Self {
48 path: Vec::new(),
49 waypoint: 0,
50 max_speed,
51 arrival_radius: 0.5,
52 waypoint_advance: 0.3,
53 desired_velocity: V::ZERO,
54 avoidance: AvoidanceConfig::default(),
55 avoidance_enabled: false,
56 }
57 }
58
59 pub fn set_path(&mut self, path: Vec<V>) {
61 self.waypoint = 0;
62 self.path = path;
63 self.desired_velocity = V::ZERO;
64 }
65
66 pub fn clear_path(&mut self) {
68 self.path.clear();
69 self.waypoint = 0;
70 self.desired_velocity = V::ZERO;
71 }
72
73 pub fn target(&self) -> Option<V> {
75 self.path.last().copied()
76 }
77
78 pub fn is_finished(&self, position: V) -> bool {
81 match self.target() {
82 Some(target) => position.distance(target) <= self.arrival_radius,
83 None => true,
84 }
85 }
86
87 pub fn advance(&mut self, position: V) {
89 while self.waypoint + 1 < self.path.len()
90 && position.distance(self.path[self.waypoint]) <= self.waypoint_advance
91 {
92 self.waypoint += 1;
93 }
94 }
95
96 pub fn desired_velocity(&mut self, position: V) -> V {
99 self.advance(position);
100 if self.path.is_empty() {
101 self.desired_velocity = V::ZERO;
102 return V::ZERO;
103 }
104 let waypoint = self.path[self.waypoint];
105 let distance = position.distance(waypoint);
106 let is_final = self.waypoint + 1 >= self.path.len();
107 if is_final && distance <= self.arrival_radius {
108 self.desired_velocity = V::ZERO;
109 return V::ZERO;
110 }
111 let direction = waypoint.sub(position).normalized();
112 let speed = if is_final {
113 let span = (distance - self.arrival_radius).max(0.0) / self.arrival_radius.max(1e-4);
114 self.max_speed * span.min(1.0)
115 } else {
116 self.max_speed
117 };
118 self.desired_velocity = direction.mul(speed);
119 self.desired_velocity
120 }
121
122 pub fn avoidance_velocity(&self, position: V, neighbors: &[AgentNeighbor<V>]) -> V {
128 if !self.avoidance_enabled || neighbors.is_empty() {
129 return self.desired_velocity;
130 }
131 let plane: Vec<Neighbor2> = neighbors
132 .iter()
133 .map(|n| {
134 let p = n.position.nav2();
135 let v = n.velocity.nav2();
136 Neighbor2 {
137 position: glam::Vec2::new(p[0], p[1]),
138 velocity: glam::Vec2::new(v[0], v[1]),
139 radius: n.radius,
140 }
141 })
142 .collect();
143 let desired = self.desired_velocity.nav2();
144 let resolved = resolve(
145 glam::Vec2::new(desired[0], desired[1]),
146 glam::Vec2::new(position.nav2()[0], position.nav2()[1]),
147 &plane,
148 &self.avoidance,
149 );
150 V::from_nav2([resolved.x, resolved.y], self.desired_velocity.height())
151 }
152}