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}