diff options
Diffstat (limited to 'server/src/customer/movement.rs')
-rw-r--r-- | server/src/customer/movement.rs | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/server/src/customer/movement.rs b/server/src/customer/movement.rs new file mode 100644 index 00000000..0ddabd0b --- /dev/null +++ b/server/src/customer/movement.rs @@ -0,0 +1,56 @@ +use crate::protocol::PacketS; +use glam::{IVec2, Vec2}; +use std::collections::HashSet; + +pub struct MovementBase { + pub position: Vec2, + pub facing: Vec2, + pub vel: Vec2, +} + +impl MovementBase { + pub fn update(&mut self, map: &HashSet<IVec2>, direction: Vec2, dt: f32) -> PacketS { + let direction = direction.normalize_or_zero(); + if direction.length() > 0.1 { + self.facing = direction + (self.facing - direction) * (-dt * 10.).exp(); + } + let rot = self.facing.x.atan2(self.facing.y); + self.vel += direction * dt * 0.5; + self.position += self.vel; + self.vel = self.vel * (-dt * 5.).exp(); + collide_player(self, map); + PacketS::Position { + pos: self.position, + rot, + } + } +} + +const PLAYER_SIZE: f32 = 0.4; +pub fn collide_player(p: &mut MovementBase, map: &HashSet<IVec2>) { + for xo in -1..=1 { + for yo in -1..=1 { + let tile = IVec2::new(xo, yo) + p.position.as_ivec2(); + if map.contains(&tile) { + continue; + } + let tile = tile.as_vec2(); + let d = aabb_circle_distance(tile, tile + Vec2::ONE, p.position); + if d > PLAYER_SIZE { + continue; + } + let h = 0.01; + let d_sample_x = + aabb_circle_distance(tile, tile + Vec2::ONE, p.position + Vec2::new(h, 0.)); + let d_sample_y = + aabb_circle_distance(tile, tile + Vec2::ONE, p.position + Vec2::new(0., h)); + let grad = (Vec2::new(d_sample_x, d_sample_y) - d) / h; + + p.position += (PLAYER_SIZE - d) * grad; + p.vel -= grad * grad.dot(p.vel); + } + } +} +pub fn aabb_circle_distance(min: Vec2, max: Vec2, p: Vec2) -> f32 { + (p - p.clamp(min, max)).length() +} |