Skip to main content

engine/
math.rs

1/**----------------------------------------------------------------------
2*!  Common math helpers used across the engine and game code.
3*?  Move `current` towards `target` by at most `max_delta`.
4*?  Mirrors Unity's `Mathf.MoveTowards`: if the distance is smaller than
5*?  `max_delta` the result snaps exactly to `target`, avoiding overshooting.
6*----------------------------------------------------------------------**/
7#[inline]
8pub fn move_towards(current: f32, target: f32, max_delta: f32) -> f32 {
9    if (target - current).abs() <= max_delta {
10        target
11    } else {
12        current + max_delta.copysign(target - current)
13    }
14}
15
16//? Unit tests for `move_towards` to verify correct behavior in various scenarios.
17#[cfg(test)]
18mod tests {
19    //? Import the parent module to access `move_towards`.
20    use super::*;
21
22    //* Test that it snaps to target when within max_delta.
23    #[test]
24    fn snap_when_close() {
25        assert_eq!(move_towards(9.5, 10.0, 1.0), 10.0);
26    }
27
28    //* Test that it moves by max_delta when far from target.
29    #[test]
30    fn advance_positive() {
31        assert!((move_towards(0.0, 10.0, 3.0) - 3.0).abs() < f32::EPSILON);
32    }
33
34    //* Test that it moves by max_delta when far from target in the negative direction.
35    #[test]
36    fn advance_negative() {
37        assert!((move_towards(5.0, 0.0, 2.0) - 3.0).abs() < f32::EPSILON);
38    }
39
40    //* Test that it does not overshoot the target when within max_delta.
41    #[test]
42    fn zero_delta_no_movement() {
43        assert!((move_towards(5.0, 10.0, 0.0) - 5.0).abs() < f32::EPSILON);
44    }
45}