feat(ai): add NavAgent ECS component

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-26 14:43:59 +09:00
parent 6121530bfe
commit 5b3b06c318
2 changed files with 87 additions and 0 deletions

View File

@@ -1,7 +1,9 @@
pub mod nav_agent;
pub mod navmesh; pub mod navmesh;
pub mod pathfinding; pub mod pathfinding;
pub mod steering; pub mod steering;
pub use nav_agent::NavAgent;
pub use navmesh::{NavMesh, NavTriangle}; pub use navmesh::{NavMesh, NavTriangle};
pub use pathfinding::find_path; pub use pathfinding::find_path;
pub use steering::{SteeringAgent, seek, flee, arrive, wander, follow_path}; pub use steering::{SteeringAgent, seek, flee, arrive, wander, follow_path};

View File

@@ -0,0 +1,85 @@
use voltex_math::Vec3;
/// ECS component for AI pathfinding navigation.
#[derive(Debug, Clone)]
pub struct NavAgent {
pub target: Option<Vec3>,
pub speed: f32,
pub path: Vec<Vec3>,
pub current_waypoint: usize,
pub reached: bool,
}
impl NavAgent {
pub fn new(speed: f32) -> Self {
NavAgent {
target: None,
speed,
path: Vec::new(),
current_waypoint: 0,
reached: false,
}
}
pub fn set_target(&mut self, target: Vec3) {
self.target = Some(target);
self.path.clear();
self.current_waypoint = 0;
self.reached = false;
}
pub fn clear_target(&mut self) {
self.target = None;
self.path.clear();
self.current_waypoint = 0;
self.reached = false;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_defaults() {
let agent = NavAgent::new(5.0);
assert!((agent.speed - 5.0).abs() < 1e-6);
assert!(agent.target.is_none());
assert!(agent.path.is_empty());
assert_eq!(agent.current_waypoint, 0);
assert!(!agent.reached);
}
#[test]
fn test_set_target() {
let mut agent = NavAgent::new(3.0);
agent.set_target(Vec3::new(10.0, 0.0, 5.0));
assert!(agent.target.is_some());
let t = agent.target.unwrap();
assert!((t.x - 10.0).abs() < 1e-6);
assert!(!agent.reached);
}
#[test]
fn test_set_target_clears_path() {
let mut agent = NavAgent::new(3.0);
agent.path = vec![Vec3::new(1.0, 0.0, 0.0), Vec3::new(2.0, 0.0, 0.0)];
agent.current_waypoint = 1;
agent.set_target(Vec3::new(5.0, 0.0, 5.0));
assert!(agent.path.is_empty());
assert_eq!(agent.current_waypoint, 0);
}
#[test]
fn test_clear_target() {
let mut agent = NavAgent::new(3.0);
agent.set_target(Vec3::new(10.0, 0.0, 5.0));
agent.path = vec![Vec3::new(1.0, 0.0, 0.0)];
agent.reached = true;
agent.clear_target();
assert!(agent.target.is_none());
assert!(agent.path.is_empty());
assert_eq!(agent.current_waypoint, 0);
assert!(!agent.reached);
}
}