diff options
| author | Yusuf Elsharawy <yusufse-2004@hotmail.com> | 2025-11-10 20:05:46 +0000 |
|---|---|---|
| committer | Yusuf Elsharawy <yusufse-2004@hotmail.com> | 2025-11-10 20:10:38 +0000 |
| commit | b1c7a57e72ab7359191249d76ec84d6cae524e2a (patch) | |
| tree | c533911f87b1641d893de5ab68ed05c2558b1cba /dungeon/src/pos.rs | |
| parent | graphics: decouple sdl & wayland (diff) | |
| download | DungeonCrawl-b1c7a57e72ab7359191249d76ec84d6cae524e2a.tar.gz DungeonCrawl-b1c7a57e72ab7359191249d76ec84d6cae524e2a.tar.bz2 DungeonCrawl-b1c7a57e72ab7359191249d76ec84d6cae524e2a.zip | |
Refactored some code, implemented player movement
Diffstat (limited to 'dungeon/src/pos.rs')
| -rw-r--r-- | dungeon/src/pos.rs | 160 |
1 files changed, 154 insertions, 6 deletions
diff --git a/dungeon/src/pos.rs b/dungeon/src/pos.rs index e3365ef..623d914 100644 --- a/dungeon/src/pos.rs +++ b/dungeon/src/pos.rs @@ -12,7 +12,7 @@ use rand::{ use std::{ fmt::Display, - ops::{AddAssign, SubAssign}, + ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}, }; use crate::{MAP_SIZE_USIZE, map::MAP_SIZE}; @@ -499,6 +499,18 @@ impl FPos { self.1 } + /// Returns the component-wise absolute value of `FPos`. + #[must_use] + pub const fn abs(&self) -> Self { + Self(self.0.abs(), self.1.abs()) + } + + /// Returns the euclidean magnitude of `FPos`. + #[must_use] + pub fn magnitude(&self) -> f32 { + (self.0 * self.0 + self.1 * self.1).sqrt() + } + /// Steps `FPos` a given floating amount in the `Direction` `dir`. /// /// Returns `None` if the floating position wraps. @@ -534,6 +546,90 @@ impl FPos { Some(Self(x, y)) } + /// Moves from one position towards another by at most some euclidean distance. + /// Returns the distance moved. + /// + /// # Examples + /// Note: some assertions may be commented out, as they would fail due to floating-point error. + /// + /// ``` + /// use dungeon::FPos; + /// + /// let mut fpos1 = FPos::new(0.0,0.0); + /// let fpos2 = FPos::new(0.0,1.0); + /// let moved = fpos1.move_towards(fpos2, 0.6); + /// assert_eq!(moved, 0.6); + /// assert_eq!(fpos1, FPos::new(0.0, 0.6)); + /// let moved = fpos1.move_towards(fpos2, 0.6); + /// // assert_eq!(moved, 0.4); + /// assert_eq!(fpos1, FPos::new(0.0, 1.0)); + /// ``` + /// + pub fn move_towards(&mut self, goal: Self, by: f32) -> f32 { + let diff = goal - *self; + let dist = diff.magnitude(); + if by >= dist { + *self = goal; + dist + } else { + *self += diff * by / dist; + by + } + } + /// Equivalent to `move_towards` but returns a copy, discarding the distance moved. + /// + /// # Examples + /// + /// ``` + /// use dungeon::FPos; + /// + /// let fpos1 = FPos::new(0.0,0.0); + /// let fpos2 = FPos::new(0.0,1.0); + /// let fpos1 = fpos1.moved_towards(fpos2, 0.6); + /// assert_eq!(fpos1, FPos::new(0.0, 0.6)); + /// let fpos1 = fpos1.moved_towards(fpos2, 0.6); + /// assert_eq!(fpos1, FPos::new(0.0, 1.0)); + /// ``` + #[must_use] + pub fn moved_towards(mut self, goal: Self, by: f32) -> Self { + self.move_towards(goal, by); + self + } + + /// Moves from one position towards another by at most some manhattan distance. + /// Prefers vertical movement over horizontal movement. + /// Returns the distance moved. + /// + /// # Examples + /// Note: some assertions may be commented out, as they would fail due to floating-point error. + /// + /// ``` + /// use dungeon::FPos; + /// + /// let mut fpos1 = FPos::new(0.0,0.0); + /// let fpos2 = FPos::new(1.0,1.0); + /// let moved = fpos1.move_towards_manhattan(fpos2, 0.6); + /// assert_eq!(moved, 0.6); + /// assert_eq!(fpos1, FPos::new(0.0, 0.6)); + /// let moved = fpos1.move_towards_manhattan(fpos2, 0.6); + /// assert_eq!(moved, 0.6); + /// // assert_eq!(fpos1, FPos::new(0.2, 1.0)); + /// let moved = fpos1.move_towards_manhattan(fpos2, 0.6); + /// assert_eq!(moved, 0.6); + /// // assert_eq!(fpos1, FPos::new(0.8, 1.0)); + /// let moved = fpos1.move_towards_manhattan(fpos2, 0.6); + /// // assert_eq!(moved, 0.2); + /// assert_eq!(fpos1, FPos::new(1.0, 1.0)); + /// ``` + /// + pub fn move_towards_manhattan(&mut self, goal: Self, by: f32) -> f32 { + let vert_checkpoint = Self(self.0, goal.1); + let mut rem = by; + rem -= self.move_towards(vert_checkpoint, rem); + rem -= self.move_towards(goal, rem); + by - rem + } + /// Computes the absolute difference between to positions /// /// # Examples @@ -548,10 +644,8 @@ impl FPos { /// ``` /// #[must_use] - pub const fn abs_diff(self, other: Self) -> Self { - let x = (self.0 - other.0).abs(); - let y = (self.1 - other.1).abs(); - Self(x, y) + pub fn abs_diff(self, other: Self) -> Self { + (self - other).abs() } /// Returns the manhattan distance between `self` and `other` @@ -566,11 +660,65 @@ impl FPos { /// assert_eq!(fpos1.manhattan(fpos2), 1.5); /// ``` #[must_use] - pub const fn manhattan(self, other: Self) -> f32 { + pub fn manhattan(self, other: Self) -> f32 { let abs_diff = Self::abs_diff(self, other); abs_diff.0 + abs_diff.1 } } + +impl AddAssign<Self> for FPos { + fn add_assign(&mut self, rhs: Self) { + self.0 += rhs.0; + self.1 += rhs.1; + } +} +impl Add<Self> for FPos { + type Output = Self; + fn add(mut self, rhs: Self) -> Self { + self += rhs; + self + } +} +impl SubAssign<Self> for FPos { + fn sub_assign(&mut self, rhs: Self) { + self.0 -= rhs.0; + self.1 -= rhs.1; + } +} +impl Sub<Self> for FPos { + type Output = Self; + fn sub(mut self, rhs: Self) -> Self { + self -= rhs; + self + } +} +impl MulAssign<f32> for FPos { + fn mul_assign(&mut self, rhs: f32) { + self.0 *= rhs; + self.1 *= rhs; + } +} +impl Mul<f32> for FPos { + type Output = Self; + fn mul(mut self, rhs: f32) -> Self { + self *= rhs; + self + } +} +impl DivAssign<f32> for FPos { + fn div_assign(&mut self, rhs: f32) { + self.0 /= rhs; + self.1 /= rhs; + } +} +impl Div<f32> for FPos { + type Output = Self; + fn div(mut self, rhs: f32) -> Self { + self /= rhs; + self + } +} + impl Default for FPos { /// Returns a default postion at the origin (0,0) /// |