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: usize = 0;
10const CAT_SPELLS: usize = 1;
11
12pub type Entities = Packo<256, Entity, 2, u8>;
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 u8 | rhs as u8)
42    }
43}
44
45#[derive(Debug, Default)]
46pub struct Components(u8);
47
48impl Components {
49    pub fn has(&self, t: Component) -> bool {
50        self.0 & t as u8 > 0
51    }
52
53    pub fn add(&mut self, t: Component) {
54        self.0 |= t as u8;
55    }
56
57    pub fn rem(&mut self, t: Component) {
58        self.0 &= !(t as u8);
59    }
60}
61
62impl From<Component> for Components {
63    fn from(value: Component) -> Self {
64        Components(value as u8)
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, T = VX>([T; S]);
90
91impl<const S: usize, T> Default for Vec<S, T> {
92    fn default() -> Self {
93        Self(unsafe { MaybeUninit::zeroed().assume_init() })
94    }
95}
96
97pub type Vec2i = Vec<2, u8>;
98pub type Vec2 = Vec<2>;
99pub type Vec3 = Vec<3>;
100pub type Vec4 = Vec<4>;
101
102#[derive(Debug, Default)]
103pub struct Spatial {
104    // pub translation: Vec3,
105    // pub scale: Vec3,
106    // pub rotation: Vec4,
107    pub pos: Vec2i,
108}
109
110#[derive(Debug, Default)]
111pub struct Entity {
112    pub id: u8,
113    pub components: Components,
114    pub spatial: Spatial,
115    pub life: u8,
116    pub damage: u8,
117    pub cost: u8,
118}
119
120impl Display for Entity {
121    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122        write!(f, "ID:{}//", self.id)?;
123        for c in ALL_COMPONENTS {
124            if self.components.has(c) {
125                match c {
126                    Component::Spatial => write!(
127                        f,
128                        "POS:{},{}//",
129                        self.spatial.pos.0[0],
130                        self.spatial.pos.0[1],
131                        // "POS:{},{},{}//",
132                        // self.spatial.translation.0[0],
133                        // self.spatial.translation.0[1],
134                        // self.spatial.translation.0[2]
135                    )?,
136                    Component::Player => f.write_str("Player//")?,
137                    Component::Life => write!(f, "Life:{}//", self.life)?,
138                    Component::Damage => write!(f, "Damage:{}//", self.damage)?,
139                    Component::Cost => write!(f, "Cost:{}//", self.cost)?,
140                    Component::Consume => write!(f, "Consumable//")?,
141                    _ => {}
142                };
143            }
144        }
145        Ok(())
146    }
147}
148
149fn game_reset(e: &mut Entities) -> u8 {
150    e.reset();
151
152    let p = e.insert(Entity {
153        components: Component::Player + Component::Spatial + Component::Life.into(),
154        life: 100,
155        ..Default::default()
156    });
157    e[p].id = p;
158
159    let potion = e.nestc(
160        p,
161        CAT_INVENTORY,
162        Entity {
163            components: Component::Life + Component::Consume,
164            life: 50,
165            ..Default::default()
166        },
167    );
168    e[potion].id = potion;
169
170    let firebolt = e.nestc(
171        p,
172        CAT_SPELLS,
173        Entity {
174            components: Component::Damage + Component::Cost,
175            damage: 10,
176            cost: 5,
177            ..Default::default()
178        },
179    );
180    e[firebolt].id = firebolt;
181
182    let heal = e.nestc(
183        p,
184        CAT_SPELLS,
185        Entity {
186            components: Component::Life + Component::Cost,
187            life: 10,
188            cost: 5,
189            ..Default::default()
190        },
191    );
192    e[heal].id = heal;
193
194    p
195}
196
197fn main() {
198    let mut e = Entities::default();
199    let p = game_reset(&mut e);
200
201    println!("Player: {}", e[p]);
202    for e in e.childsc(p, CAT_INVENTORY) {
203        println!("Item: {e}");
204    }
205    for e in e.childsc(p, CAT_SPELLS) {
206        println!("Spell: {e}");
207    }
208
209    println!("{e}");
210}