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}