aboutsummaryrefslogtreecommitdiff
path: root/server/bot/src/pathfinding.rs
diff options
context:
space:
mode:
Diffstat (limited to 'server/bot/src/pathfinding.rs')
-rw-r--r--server/bot/src/pathfinding.rs69
1 files changed, 67 insertions, 2 deletions
diff --git a/server/bot/src/pathfinding.rs b/server/bot/src/pathfinding.rs
index 4aa7c2ff..f9f213fa 100644
--- a/server/bot/src/pathfinding.rs
+++ b/server/bot/src/pathfinding.rs
@@ -15,10 +15,14 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+use crate::PacketSink;
use hurrycurry_game_core::Game;
-use hurrycurry_protocol::glam::{IVec2, Vec2};
#[cfg(feature = "debug_events")]
-use hurrycurry_protocol::{DebugEvent, DebugEventDisplay, PlayerID};
+use hurrycurry_protocol::{DebugEvent, DebugEventDisplay};
+use hurrycurry_protocol::{
+ PacketS, PlayerID,
+ glam::{IVec2, Vec2},
+};
use log::{debug, trace};
use std::{
cmp::Ordering,
@@ -30,13 +34,39 @@ use std::{
pub struct Path {
segments: Vec<Vec2>,
seg_time: f32,
+ last_dir: Vec2,
+ last_boost: bool,
}
impl Path {
pub const EMPTY: Path = Path {
seg_time: 0.,
segments: Vec::new(),
+ last_boost: false,
+ last_dir: Vec2::ZERO,
};
+ pub fn update(
+ &mut self,
+ out: &mut PacketSink,
+ player: PlayerID,
+ position: Vec2,
+ dt: f32,
+ speed: f32,
+ allow_boost: bool,
+ ) {
+ let dir = speed * self.next_direction(position, dt);
+ let boost = allow_boost && self.is_stuck(0.5);
+ if dir.distance(self.last_dir) > 0.1 || boost != self.last_boost {
+ self.last_dir = dir;
+ self.last_boost = boost;
+ out.push(PacketS::Movement {
+ player,
+ dir,
+ boost,
+ pos: None,
+ });
+ }
+ }
pub fn next_direction(&mut self, position: Vec2, dt: f32) -> Vec2 {
if let Some(next) = self.segments.last().copied() {
trace!("next {next}");
@@ -171,5 +201,40 @@ pub fn find_path(game: &Game, from: IVec2, to: IVec2) -> Option<Path> {
Some(Path {
segments,
seg_time: 0.,
+ last_boost: false,
+ last_dir: Vec2::ZERO,
})
}
+
+#[derive(Debug, Clone)]
+pub struct HoldLocation {
+ target: Vec2,
+ facing: Vec2,
+ last_dir: Vec2,
+}
+impl HoldLocation {
+ pub fn new(target: Vec2, facing: Vec2) -> Self {
+ Self {
+ facing,
+ target,
+ last_dir: Vec2::ZERO,
+ }
+ }
+ pub fn update(&mut self, out: &mut PacketSink, player: PlayerID, pos: Vec2) {
+ let diff = (self.target + 0.5) - pos;
+ let dir = match diff.length() {
+ x if x < 0.3 => self.facing.clamp_length_max(1.) * 0.4, // TODO rotation not updating
+ x if x < 1.0 => diff.normalize() * 0.6,
+ _ => diff.normalize(),
+ };
+ if dir.distance(self.last_dir) > 0.1 {
+ self.last_dir = dir;
+ out.push(PacketS::Movement {
+ player,
+ dir,
+ boost: false,
+ pos: None,
+ });
+ }
+ }
+}