Skip to main content

aeon_fighter/
geom.rs

1//! Integer geometry. All match units are **subpixels** (256 per pixel).
2//! The sim never touches floats so a later rollback layer can hash state.
3
4pub const SUB: i32 = 256;
5pub const TICK_HZ: u32 = 60;
6
7/// Convert whole pixels to subpixels.
8pub const fn px(pixels: i32) -> i32 {
9    pixels * SUB
10}
11
12#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
13pub struct Vec2i {
14    pub x: i32,
15    pub y: i32,
16}
17
18impl Vec2i {
19    pub const ZERO: Self = Self { x: 0, y: 0 };
20
21    pub const fn new(x: i32, y: i32) -> Self {
22        Self { x, y }
23    }
24}
25
26/// Axis-aligned box in world space. `x,y` is the bottom-center (fighter origin
27/// convention: feet, midline).
28#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
29pub struct Aabb {
30    pub left: i32,
31    pub right: i32,
32    pub bottom: i32,
33    pub top: i32,
34}
35
36impl Aabb {
37    pub fn from_center_size(cx: i32, bottom: i32, w: i32, h: i32) -> Self {
38        let half = w / 2;
39        Self {
40            left: cx - half,
41            right: cx + half,
42            bottom,
43            top: bottom + h,
44        }
45    }
46
47    pub fn overlaps(self, other: Self) -> bool {
48        self.left < other.right
49            && self.right > other.left
50            && self.bottom < other.top
51            && self.top > other.bottom
52    }
53
54    pub fn center_x(self) -> i32 {
55        (self.left + self.right) / 2
56    }
57
58    pub fn width(self) -> i32 {
59        self.right - self.left
60    }
61
62    pub fn height(self) -> i32 {
63        self.top - self.bottom
64    }
65}
66
67/// Box defined in fighter-local space.
68/// `x` is offset *toward facing* from the origin; `y` is up from the feet.
69#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
70pub struct LocalBox {
71    pub x: i32,
72    pub y: i32,
73    pub w: i32,
74    pub h: i32,
75}
76
77impl LocalBox {
78    pub const fn new(x: i32, y: i32, w: i32, h: i32) -> Self {
79        Self { x, y, w, h }
80    }
81
82    pub fn to_world(self, origin: Vec2i, facing_right: bool) -> Aabb {
83        let signed_x = if facing_right {
84            self.x
85        } else {
86            -self.x - self.w
87        };
88        let left = origin.x + signed_x;
89        Aabb {
90            left,
91            right: left + self.w,
92            bottom: origin.y + self.y,
93            top: origin.y + self.y + self.h,
94        }
95    }
96}