Skip to main content

entities/
entities.rs

1use std::{
2    fmt::Display,
3    mem::MaybeUninit,
4    ops::{Add, Sub},
5};
6
7use packo::*;
8
9const CAT_INVENTORY: CATS = 0;
10const CAT_SPELLS: CATS = 1;
11
12pub type Entities = Packo<1024, Entity, 2>;
13
14#[derive(Clone, Copy, Default)]
15#[repr(C)]
16pub enum Component {
17    #[default]
18    None = 0,
19    Spatial = 1 << 0,
20    Player = 1 << 1,
21    Life = 1 << 2,
22    Damage = 1 << 3,
23    Cost = 1 << 4,
24    Consume = 1 << 5,
25}
26
27const ALL_COMPONENTS: [Component; 6] = [
28    Component::Spatial,
29    Component::Player,
30    Component::Life,
31    Component::Damage,
32    Component::Cost,
33    Component::Consume,
34];
35
36impl Add for Component {
37    type Output = Components;
38
39    fn add(self, rhs: Self) -> Self::Output {
40        #[allow(clippy::suspicious_arithmetic_impl)]
41        Components(self as u32 | rhs as u32)
42    }
43}
44
45#[derive(Debug, Default)]
46pub struct Components(u32);
47
48impl Components {
49    pub fn has(&self, t: Component) -> bool {
50        self.0 & t as u32 > 0
51    }
52
53    pub fn add(&mut self, t: Component) {
54        self.0 |= t as u32;
55    }
56
57    pub fn rem(&mut self, t: Component) {
58        self.0 &= !(t as u32);
59    }
60}
61
62impl From<Component> for Components {
63    fn from(value: Component) -> Self {
64        Components(value as u32)
65    }
66}
67
68impl Add for Components {
69    type Output = Self;
70
71    fn add(self, rhs: Self) -> Self::Output {
72        #[allow(clippy::suspicious_arithmetic_impl)]
73        Components(self.0 | rhs.0)
74    }
75}
76
77impl Sub for Components {
78    type Output = Self;
79
80    fn sub(self, rhs: Self) -> Self::Output {
81        #[allow(clippy::suspicious_arithmetic_impl)]
82        Components(self.0 & !rhs.0)
83    }
84}
85
86pub type VX = f32;
87
88#[derive(Debug)]
89pub struct Vec<const S: usize>([VX; S]);
90
91impl<const S: usize> Default for Vec<S> {
92    fn default() -> Self {
93        Self(unsafe { MaybeUninit::zeroed().assume_init() })
94    }
95}
96
97pub type Vec2 = Vec<2>;
98pub type Vec3 = Vec<3>;
99pub type Vec4 = Vec<4>;
100
101#[derive(Debug, Default)]
102pub struct Spatial {
103    pub translation: Vec3,
104    pub scale: Vec3,
105    pub rotation: Vec4,
106}
107
108#[derive(Debug, Default)]
109pub struct Entity {
110    pub id: IDX,
111    pub components: Components,
112    pub spatial: Spatial,
113    pub life: u8,
114    pub damage: u8,
115    pub cost: u8,
116}
117
118impl Display for Entity {
119    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120        write!(f, "ID:{}//", self.id)?;
121        for c in ALL_COMPONENTS {
122            if self.components.has(c) {
123                match c {
124                    Component::Spatial => write!(
125                        f,
126                        "POS:{},{},{}//",
127                        self.spatial.translation.0[0],
128                        self.spatial.translation.0[1],
129                        self.spatial.translation.0[2]
130                    )?,
131                    Component::Player => f.write_str("Player//")?,
132                    Component::Life => write!(f, "Life:{}//", self.life)?,
133                    Component::Damage => write!(f, "Damage:{}//", self.damage)?,
134                    Component::Cost => write!(f, "Cost:{}//", self.cost)?,
135                    Component::Consume => write!(f, "Consumable//")?,
136                    _ => {}
137                };
138            }
139        }
140        Ok(())
141    }
142}
143
144fn game_reset(e: &mut Entities) -> IDX {
145    e.reset();
146
147    let p = e.insert(Entity {
148        components: Component::Player + Component::Spatial + Component::Life.into(),
149        life: 100,
150        ..Default::default()
151    });
152    e[p].id = p;
153
154    let potion = e.nestc(
155        p,
156        CAT_INVENTORY,
157        Entity {
158            components: Component::Life + Component::Consume,
159            life: 50,
160            ..Default::default()
161        },
162    );
163    e[potion].id = potion;
164
165    let firebolt = e.nestc(
166        p,
167        CAT_SPELLS,
168        Entity {
169            components: Component::Damage + Component::Cost,
170            damage: 10,
171            cost: 5,
172            ..Default::default()
173        },
174    );
175    e[firebolt].id = firebolt;
176
177    let heal = e.nestc(
178        p,
179        CAT_SPELLS,
180        Entity {
181            components: Component::Life + Component::Cost,
182            life: 10,
183            cost: 5,
184            ..Default::default()
185        },
186    );
187    e[heal].id = heal;
188
189    p
190}
191
192fn main() {
193    let mut e = Entities::default();
194    let p = game_reset(&mut e);
195
196    println!("Player: {}", e[p]);
197    for e in e.childsc(p, CAT_INVENTORY) {
198        println!("Item: {e}");
199    }
200    for e in e.childsc(p, CAT_SPELLS) {
201        println!("Spell: {e}");
202    }
203}