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 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 )?,
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}