1use anymap::AnyMap;
7use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind};
8use std::any::{Any, TypeId};
9use std::collections::HashMap;
10use std::io;
11use std::io::stdout;
12use teng::components::Component as TengComponent;
13use teng::rendering::pixel::Pixel;
14use teng::rendering::renderer::Renderer;
15use teng::{BreakingAction, Game, SetupInfo, SharedState};
16
17struct Position {
19 x: usize,
20 y: usize,
21}
22
23struct Draw {
25 ch: char,
26}
27
28#[derive(Hash, Eq, PartialEq, Clone, Copy)]
30struct Entity(usize);
31
32struct DrawSystem;
34
35impl TengComponent<Ecs> for DrawSystem {
36 fn render(
37 &self,
38 renderer: &mut dyn Renderer,
39 shared_state: &SharedState<Ecs>,
40 depth_base: i32,
41 ) {
42 let ecs = &shared_state.custom;
43 for (position, draw) in ecs.entities.iter().filter_map(|entity| {
44 let position = ecs.get_component::<Position>(*entity)?;
45 let draw = ecs.get_component::<Draw>(*entity)?;
46 Some((position, draw))
47 }) {
48 renderer.render_pixel(position.x, position.y, Pixel::new(draw.ch), depth_base);
49 }
50 }
51}
52
53struct PhysicsSystem;
55
56impl TengComponent<Ecs> for PhysicsSystem {
57 fn update(&mut self, _update_info: teng::UpdateInfo, shared_state: &mut SharedState<Ecs>) {
58 let ecs = &mut shared_state.custom;
59 for &entity in &ecs.entities {
60 let Some(position) = ecs.components.get_mut_from_entity::<Position>(entity) else {
61 continue;
62 };
63 position.y += 1;
64 if position.y >= shared_state.display_info.height() {
65 position.y = 0;
66 }
67 }
68 }
69}
70
71fn main() -> io::Result<()> {
72 teng::terminal_setup()?;
73 teng::install_panic_handler();
74
75 let mut game = Game::new(stdout());
76 game.install_recommended_components();
77 game.add_component(Box::new(EcsComponent::default()));
78 game.add_component(Box::new(DrawSystem));
79 game.add_component(Box::new(PhysicsSystem));
80 game.run()?;
81
82 teng::terminal_cleanup()?;
83 Ok(())
84}
85
86struct ComponentList {
87 inner: AnyMap,
88}
89
90impl Default for ComponentList {
91 fn default() -> Self {
92 Self::new()
93 }
94}
95
96impl ComponentList {
97 fn new() -> Self {
98 Self {
99 inner: AnyMap::new(),
100 }
101 }
102
103 fn add_to_entity<T: 'static>(&mut self, entity: Entity, component: T) {
104 let map = self.get_mut::<T>().expect("Component not registered");
105 map.insert(entity, component);
106 }
107
108 fn get_from_entity<T: 'static>(&self, entity: Entity) -> Option<&T> {
109 let map = self.get::<T>()?;
110 map.get(&entity)
111 }
112
113 fn get_mut_from_entity<T: 'static>(&mut self, entity: Entity) -> Option<&mut T> {
114 let map = self.get_mut::<T>()?;
115 map.get_mut(&entity)
116 }
117
118 fn get<T: 'static>(&self) -> Option<&HashMap<Entity, T>> {
119 self.inner.get::<HashMap<Entity, T>>()
120 }
121
122 fn get_mut<T: 'static>(&mut self) -> Option<&mut HashMap<Entity, T>> {
123 self.inner.get_mut::<HashMap<Entity, T>>()
124 }
125
126 fn register<T: 'static>(&mut self) {
127 self.inner.insert::<HashMap<Entity, T>>(HashMap::new());
128 }
129}
130
131#[derive(Default)]
133struct Ecs {
134 entities: Vec<Entity>,
135 max_key: usize,
136 components: ComponentList,
137}
138
139impl Ecs {
140 fn new() -> Self {
141 Self {
142 entities: Vec::new(),
143 max_key: 0,
144 components: ComponentList::new(),
145 }
146 }
147
148 fn create_entity(&mut self) -> Entity {
149 let entity = Entity(self.max_key);
150 self.entities.push(entity);
151 self.max_key += 1;
152 entity
153 }
154
155 fn add_component<T: 'static>(&mut self, entity: Entity, component: T) {
156 self.components.add_to_entity(entity, component);
157 }
158
159 fn get_component<T: 'static>(&self, entity: Entity) -> Option<&T> {
160 self.components.get_from_entity(entity)
161 }
162
163 fn get_mut_component<T: 'static>(&mut self, entity: Entity) -> Option<&mut T> {
164 self.components.get_mut_from_entity(entity)
165 }
166}
167
168#[derive(Default)]
170struct EcsComponent {
171 width: usize,
172 height: usize,
173}
174
175impl TengComponent<Ecs> for EcsComponent {
176 fn setup(&mut self, setup_info: &SetupInfo, shared_state: &mut SharedState<Ecs>) {
177 self.width = setup_info.display_info.width();
178 self.height = setup_info.display_info.height();
179
180 let ecs = &mut shared_state.custom;
181 ecs.components.register::<Position>();
182 ecs.components.register::<Draw>();
183 }
184
185 fn on_event(
186 &mut self,
187 event: Event,
188 shared_state: &mut SharedState<Ecs>,
189 ) -> Option<BreakingAction> {
190 let ecs = &mut shared_state.custom;
191 if let Event::Key(KeyEvent {
192 kind: KeyEventKind::Press,
193 code: KeyCode::Char(ch),
194 ..
195 }) = event
196 {
197 let entity = ecs.create_entity();
199 let x = rand::random::<usize>() % self.width;
200 let y = rand::random::<usize>() % self.height;
201 ecs.add_component(entity, Position { x, y });
202 ecs.add_component(entity, Draw { ch });
203 }
204
205 None
206 }
207}