diff options
Diffstat (limited to 'server/src/customer/pathfinding.rs')
-rw-r--r-- | server/src/customer/pathfinding.rs | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/server/src/customer/pathfinding.rs b/server/src/customer/pathfinding.rs new file mode 100644 index 00000000..d25c6913 --- /dev/null +++ b/server/src/customer/pathfinding.rs @@ -0,0 +1,83 @@ +use super::movement::MovementBase; +use crate::protocol::PacketS; +use glam::{IVec2, Vec2}; +use log::debug; +use std::{ + cmp::Ordering, + collections::{BinaryHeap, HashMap, HashSet}, +}; + +pub struct Path(Vec<Vec2>); + +impl Path { + pub fn execute_tick( + &mut self, + customer: &mut MovementBase, + walkable: &HashSet<IVec2>, + dt: f32, + ) -> PacketS { + if let Some(next) = self.0.last().copied() { + debug!("next {next}"); + if next.distance(customer.position) < if self.0.len() == 1 { 0.1 } else { 0.6 } { + self.0.pop(); + } + customer.update(&walkable, next - customer.position, dt) + } else { + customer.update(&walkable, Vec2::ZERO, dt) + } + } + pub fn is_done(&self) -> bool { + self.0.is_empty() + } +} + +pub fn find_path(map: &HashSet<IVec2>, from: IVec2, to: IVec2) -> Option<Path> { + #[derive(Debug, PartialEq, Eq)] + struct Open(i32, IVec2, IVec2); + impl PartialOrd for Open { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + self.0.partial_cmp(&other.0) + } + } + impl Ord for Open { + fn cmp(&self, other: &Self) -> Ordering { + self.0.cmp(&other.0) + } + } + + let mut visited = HashMap::new(); + let mut open = BinaryHeap::new(); + open.push(Open(1, from, from)); + + loop { + let Some(Open(_, p, f)) = open.pop() else { + eprintln!("{visited:?}"); + return None; + }; + if visited.contains_key(&p) { + continue; + } + visited.insert(p, f); + if p == to { + break; + } + for d in [IVec2::NEG_X, IVec2::NEG_Y, IVec2::X, IVec2::Y] { + let n = p + d; + if map.contains(&n) { + open.push(Open(-d.distance_squared(to), n, p)); + } + } + } + + let mut path = Vec::new(); + let mut c = to; + loop { + path.push(c.as_vec2() + 0.5); + let cn = visited[&c]; + if cn == c { + break; + } + c = cn + } + Some(Path(path)) +} |