summaryrefslogtreecommitdiff
path: root/dungeon/src/pos.rs
diff options
context:
space:
mode:
authorYusuf Elsharawy <yusufse-2004@hotmail.com>2025-11-10 20:05:46 +0000
committerYusuf Elsharawy <yusufse-2004@hotmail.com>2025-11-10 20:10:38 +0000
commitb1c7a57e72ab7359191249d76ec84d6cae524e2a (patch)
treec533911f87b1641d893de5ab68ed05c2558b1cba /dungeon/src/pos.rs
parentgraphics: decouple sdl & wayland (diff)
downloadDungeonCrawl-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.rs160
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)
///