Imrpoved component structure

This commit is contained in:
2025-11-26 22:05:39 +01:00
parent 7096849b65
commit 3f07ca0ff6
5 changed files with 93 additions and 9 deletions
+4
View File
@@ -10,6 +10,10 @@ impl Component for Velocity {
apply_velocity(tick, self.0.x, &mut position.x);
apply_velocity(tick, self.0.y, &mut position.y);
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
}
fn apply_velocity(tick: u16, velocity: i32, x: &mut u16) -> bool {
+3 -2
View File
@@ -19,10 +19,11 @@ pub fn tick(engine: &Arc<Engine>) {
}
pub fn key(engine: &Arc<Engine>) {
crossterm::terminal::enable_raw_mode().unwrap();
engine.thread("Main.key", |engine| {
loop {
// Pass an event to the thread
engine.emit_event(crossterm::event::read().unwrap());
}
});
}
+37 -2
View File
@@ -3,8 +3,6 @@ pub mod components;
use osmium::{renderer::Point, terminal};
fn main() {
terminal::hide_cursor().unwrap();
let engine = osmium::init();
let my_rect = engine.entity(|r| {
@@ -15,6 +13,43 @@ fn main() {
my_rect.component(components::Velocity(Point { x: 0, y: 0 }));
components::threads::tick(&engine);
components::threads::key(&engine);
engine.on_event({
let my_rect = my_rect.clone();
move |e: &crossterm::event::Event| {
if let Some(key_event) = e.as_key_event() {
match key_event.code {
crossterm::event::KeyCode::Right => {
my_rect.update_component(|c: &mut components::Velocity| {
c.0.x = 100;
});
}
crossterm::event::KeyCode::Left => {
my_rect.update_component(|c: &mut components::Velocity| {
c.0.x = -100;
});
}
crossterm::event::KeyCode::Down => {
my_rect.update_component(|c: &mut components::Velocity| {
c.0.y = 100;
});
}
crossterm::event::KeyCode::Up => {
my_rect.update_component(|c: &mut components::Velocity| {
c.0.y = -100;
});
}
_ => {}
}
}
}
});
terminal::hide_cursor().unwrap();
engine.start();
terminal::show_cursor().unwrap();
+22 -5
View File
@@ -1,4 +1,8 @@
use std::sync::{Arc, Mutex, MutexGuard};
use std::{
any::{Any, TypeId},
collections::HashMap,
sync::{Arc, Mutex, MutexGuard},
};
use crate::{Renderer, renderer::Point};
@@ -9,11 +13,13 @@ pub trait Component: Send + Sync {
fn init(&mut self, entity: &Arc<Entity>) {}
#[allow(unused_variables)]
fn tick(&mut self, entity: &Arc<Entity>, tick: u16) {}
fn as_any_mut(&mut self) -> &mut dyn Any;
}
pub struct Entity {
pos: Mutex<Point>,
components: Mutex<Vec<Box<dyn Component>>>,
components: Mutex<HashMap<TypeId, Box<dyn Component>>>,
render: Box<dyn Fn(&mut Renderer) + Send + Sync>,
}
@@ -21,13 +27,24 @@ impl Entity {
pub fn new<F: Fn(&mut Renderer) + Send + Sync + 'static>(render: F) -> Arc<Self> {
Arc::new(Self {
pos: Mutex::new(Point { x: 0, y: 0 }),
components: Mutex::new(Vec::new()),
components: Mutex::new(HashMap::new()),
render: Box::new(render),
})
}
pub fn component<C: Component + 'static>(self: &Arc<Self>, c: C) {
self.components.lock().unwrap().push(Box::new(c));
self.components
.lock()
.unwrap()
.insert(TypeId::of::<C>(), Box::new(c));
}
pub fn update_component<C: Component + 'static, F: Fn(&mut C)>(self: &Arc<Self>, f: F) {
if let Some(c) = self.components.lock().unwrap().get_mut(&TypeId::of::<C>()) {
if let Some(c) = c.as_any_mut().downcast_mut::<C>() {
f(c)
}
}
}
pub fn render(self: &Arc<Self>, renderer: &mut Renderer) {
@@ -35,7 +52,7 @@ impl Entity {
}
pub fn tick(self: &Arc<Self>, tick: u16) {
for comp in self.components.lock().unwrap().iter_mut() {
for comp in self.components.lock().unwrap().values_mut() {
comp.tick(self, tick);
}
}
+27
View File
@@ -3,6 +3,7 @@ pub mod renderer;
pub mod terminal;
use std::{
any::{Any, TypeId},
collections::HashMap,
sync::{Arc, Mutex},
};
@@ -13,12 +14,14 @@ pub fn init() -> Arc<Engine> {
Arc::new(Engine {
threads: Mutex::new(HashMap::new()),
entities: Mutex::new(Vec::new()),
event_cb: Mutex::new(HashMap::new()),
})
}
pub struct Engine {
threads: Mutex<HashMap<String, Arc<dyn Fn(&Arc<Self>) + Send + Sync>>>,
entities: Mutex<Vec<Arc<entity::Entity>>>,
event_cb: Mutex<HashMap<TypeId, Vec<Arc<dyn Fn(&dyn Any) + Send + Sync>>>>,
}
pub fn sleep(ms: u64) {
@@ -46,6 +49,30 @@ impl Engine {
.clone()
}
pub fn on_event<E: Any + 'static, F: Fn(&E) + Send + Sync + 'static>(
self: &Arc<Self>,
callback: F,
) {
self.event_cb
.lock()
.unwrap()
.entry(TypeId::of::<E>())
.or_insert_with(|| Vec::new())
.push(Arc::new(move |e| {
if let Some(e) = e.downcast_ref() {
callback(e);
}
}));
}
pub fn emit_event<E: Any + 'static>(self: &Arc<Self>, event: E) {
if let Some(callbacks) = self.event_cb.lock().unwrap().get(&TypeId::of::<E>()) {
for cb in callbacks {
cb(&event)
}
}
}
pub fn render(self: &Arc<Self>) {
terminal::clear().unwrap();