Imrpoved component structure
This commit is contained in:
@@ -10,6 +10,10 @@ impl Component for Velocity {
|
|||||||
apply_velocity(tick, self.0.x, &mut position.x);
|
apply_velocity(tick, self.0.x, &mut position.x);
|
||||||
apply_velocity(tick, self.0.y, &mut position.y);
|
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 {
|
fn apply_velocity(tick: u16, velocity: i32, x: &mut u16) -> bool {
|
||||||
|
|||||||
@@ -19,10 +19,11 @@ pub fn tick(engine: &Arc<Engine>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn key(engine: &Arc<Engine>) {
|
pub fn key(engine: &Arc<Engine>) {
|
||||||
|
crossterm::terminal::enable_raw_mode().unwrap();
|
||||||
|
|
||||||
engine.thread("Main.key", |engine| {
|
engine.thread("Main.key", |engine| {
|
||||||
loop {
|
loop {
|
||||||
// Pass an event to the thread
|
engine.emit_event(crossterm::event::read().unwrap());
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+37
-2
@@ -3,8 +3,6 @@ pub mod components;
|
|||||||
use osmium::{renderer::Point, terminal};
|
use osmium::{renderer::Point, terminal};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
terminal::hide_cursor().unwrap();
|
|
||||||
|
|
||||||
let engine = osmium::init();
|
let engine = osmium::init();
|
||||||
|
|
||||||
let my_rect = engine.entity(|r| {
|
let my_rect = engine.entity(|r| {
|
||||||
@@ -15,6 +13,43 @@ fn main() {
|
|||||||
|
|
||||||
my_rect.component(components::Velocity(Point { x: 0, y: 0 }));
|
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();
|
engine.start();
|
||||||
|
|
||||||
terminal::show_cursor().unwrap();
|
terminal::show_cursor().unwrap();
|
||||||
|
|||||||
+22
-5
@@ -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};
|
use crate::{Renderer, renderer::Point};
|
||||||
|
|
||||||
@@ -9,11 +13,13 @@ pub trait Component: Send + Sync {
|
|||||||
fn init(&mut self, entity: &Arc<Entity>) {}
|
fn init(&mut self, entity: &Arc<Entity>) {}
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn tick(&mut self, entity: &Arc<Entity>, tick: u16) {}
|
fn tick(&mut self, entity: &Arc<Entity>, tick: u16) {}
|
||||||
|
|
||||||
|
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Entity {
|
pub struct Entity {
|
||||||
pos: Mutex<Point>,
|
pos: Mutex<Point>,
|
||||||
components: Mutex<Vec<Box<dyn Component>>>,
|
components: Mutex<HashMap<TypeId, Box<dyn Component>>>,
|
||||||
render: Box<dyn Fn(&mut Renderer) + Send + Sync>,
|
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> {
|
pub fn new<F: Fn(&mut Renderer) + Send + Sync + 'static>(render: F) -> Arc<Self> {
|
||||||
Arc::new(Self {
|
Arc::new(Self {
|
||||||
pos: Mutex::new(Point { x: 0, y: 0 }),
|
pos: Mutex::new(Point { x: 0, y: 0 }),
|
||||||
components: Mutex::new(Vec::new()),
|
components: Mutex::new(HashMap::new()),
|
||||||
render: Box::new(render),
|
render: Box::new(render),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn component<C: Component + 'static>(self: &Arc<Self>, c: C) {
|
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) {
|
pub fn render(self: &Arc<Self>, renderer: &mut Renderer) {
|
||||||
@@ -35,7 +52,7 @@ impl Entity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick(self: &Arc<Self>, tick: u16) {
|
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);
|
comp.tick(self, tick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+27
@@ -3,6 +3,7 @@ pub mod renderer;
|
|||||||
pub mod terminal;
|
pub mod terminal;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
any::{Any, TypeId},
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
@@ -13,12 +14,14 @@ pub fn init() -> Arc<Engine> {
|
|||||||
Arc::new(Engine {
|
Arc::new(Engine {
|
||||||
threads: Mutex::new(HashMap::new()),
|
threads: Mutex::new(HashMap::new()),
|
||||||
entities: Mutex::new(Vec::new()),
|
entities: Mutex::new(Vec::new()),
|
||||||
|
event_cb: Mutex::new(HashMap::new()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Engine {
|
pub struct Engine {
|
||||||
threads: Mutex<HashMap<String, Arc<dyn Fn(&Arc<Self>) + Send + Sync>>>,
|
threads: Mutex<HashMap<String, Arc<dyn Fn(&Arc<Self>) + Send + Sync>>>,
|
||||||
entities: Mutex<Vec<Arc<entity::Entity>>>,
|
entities: Mutex<Vec<Arc<entity::Entity>>>,
|
||||||
|
event_cb: Mutex<HashMap<TypeId, Vec<Arc<dyn Fn(&dyn Any) + Send + Sync>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sleep(ms: u64) {
|
pub fn sleep(ms: u64) {
|
||||||
@@ -46,6 +49,30 @@ impl Engine {
|
|||||||
.clone()
|
.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>) {
|
pub fn render(self: &Arc<Self>) {
|
||||||
terminal::clear().unwrap();
|
terminal::clear().unwrap();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user