less cringe sprite drawing
This commit is contained in:
parent
3a3f2a89f6
commit
0dc18414f1
@ -1,5 +1,5 @@
|
||||
use std::any::{Any, TypeId};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::time::Duration;
|
||||
|
||||
use sdl2::{
|
||||
@ -40,33 +40,34 @@ macro_rules! impl_from_T_for_Error {
|
||||
};
|
||||
}
|
||||
|
||||
impl_from_T_for_Error!(String, WindowBuildError, IntegerOrSdlError);
|
||||
impl_from_T_for_Error!(String, WindowBuildError, IntegerOrSdlError, &str);
|
||||
|
||||
pub struct Entity(u64, Vec<Box<dyn Component>>);
|
||||
pub type Id = u64;
|
||||
|
||||
pub struct Entity(Id, Vec<Box<dyn Component>>);
|
||||
|
||||
pub trait Component {
|
||||
fn inner_type_id(&self) -> TypeId;
|
||||
fn as_any(&mut self) -> &mut dyn Any;
|
||||
}
|
||||
|
||||
pub struct Sprite {
|
||||
path: std::path::PathBuf,
|
||||
}
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Sprite(Id);
|
||||
|
||||
pub struct Context<'context, 'game>
|
||||
where
|
||||
'game: 'context,
|
||||
{
|
||||
id_counter: &'context mut u64,
|
||||
id_counter: &'context mut Id,
|
||||
canvas: &'context mut Canvas<Window>,
|
||||
texture_creator: *const TextureCreator<WindowContext>,
|
||||
entities: &'context mut Vec<Entity>,
|
||||
systems: &'context mut Vec<Box<dyn System>>,
|
||||
textures: &'context mut HashMap<std::path::PathBuf, Texture<'game>>,
|
||||
systems: &'context mut Vec<Rc<dyn System>>,
|
||||
textures: &'context mut Vec<(Id, Texture<'game>)>,
|
||||
}
|
||||
|
||||
impl<'context, 'game> Context<'context, 'game> {
|
||||
pub fn entities_with_component<T: 'static>(&self) -> Vec<u64> {
|
||||
pub fn entities_with_component<T: 'static + Component>(&self) -> Vec<u64> {
|
||||
let entity_type_id = TypeId::of::<T>();
|
||||
self.entities
|
||||
.iter()
|
||||
@ -83,7 +84,7 @@ impl<'context, 'game> Context<'context, 'game> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn entity_component<T: 'static>(&mut self, entity_id: u64) -> &mut T {
|
||||
pub fn entity_component<T: 'static + Component>(&mut self, entity_id: u64) -> &mut T {
|
||||
let entity_type_id = TypeId::of::<T>();
|
||||
let Entity(_id, components) = self
|
||||
.entities
|
||||
@ -111,12 +112,19 @@ impl<'context, 'game> Context<'context, 'game> {
|
||||
{
|
||||
let path = path.as_ref().to_path_buf();
|
||||
let texture: Texture<'game> = unsafe { (*self.texture_creator).load_texture(&path)? };
|
||||
self.textures.insert(path.clone(), texture);
|
||||
Ok(Sprite { path })
|
||||
let id = *self.id_counter;
|
||||
*self.id_counter += 1;
|
||||
|
||||
self.textures.push((id, texture));
|
||||
Ok(Sprite(id))
|
||||
}
|
||||
|
||||
pub fn draw_sprite(&mut self, sprite: &Sprite, x: i32, y: i32) -> Result<(), Error> {
|
||||
let texture = &self.textures[&sprite.path];
|
||||
let texture = self
|
||||
.textures
|
||||
.iter()
|
||||
.find_map(|v| if v.0 == sprite.0 { Some(&v.1) } else { None })
|
||||
.ok_or_else(|| "invalid sprite id")?;
|
||||
self.canvas.copy(
|
||||
texture,
|
||||
None,
|
||||
@ -136,7 +144,7 @@ impl<'context, 'game> Context<'context, 'game> {
|
||||
self.entities.push(Entity(id, components));
|
||||
}
|
||||
|
||||
pub fn add_system(&mut self, system: Box<dyn System>) {
|
||||
pub fn add_system(&mut self, system: Rc<dyn System>) {
|
||||
system.on_add(self);
|
||||
self.systems.push(system)
|
||||
}
|
||||
@ -144,7 +152,9 @@ impl<'context, 'game> Context<'context, 'game> {
|
||||
|
||||
pub trait System {
|
||||
fn on_add(&self, _ctx: &mut Context) {}
|
||||
fn on_update(&self, _ctx: &mut Context) {}
|
||||
fn on_update(&self, _ctx: &mut Context) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Game<'a> {
|
||||
@ -157,8 +167,8 @@ pub struct Game<'a> {
|
||||
event_pump: sdl2::EventPump,
|
||||
entities: Vec<Entity>,
|
||||
components: Vec<(u64, Box<dyn Component>)>,
|
||||
systems: Vec<Box<dyn System>>,
|
||||
textures: HashMap<std::path::PathBuf, Texture<'a>>,
|
||||
systems: Vec<Rc<dyn System>>,
|
||||
textures: Vec<(Id, Texture<'a>)>,
|
||||
}
|
||||
|
||||
impl<'game> Game<'game> {
|
||||
@ -189,11 +199,11 @@ impl<'game> Game<'game> {
|
||||
entities: vec![],
|
||||
components: vec![],
|
||||
systems: vec![],
|
||||
textures: HashMap::new(),
|
||||
textures: vec![],
|
||||
})
|
||||
}
|
||||
|
||||
pub fn run<F: Fn(&mut Context)>(&mut self, f: F) {
|
||||
pub fn run(&mut self) {
|
||||
'running: loop {
|
||||
for event in self.event_pump.poll_iter() {
|
||||
match event {
|
||||
@ -207,11 +217,15 @@ impl<'game> Game<'game> {
|
||||
}
|
||||
self.canvas.set_draw_color(Color::RGB(60, 180, 180));
|
||||
self.canvas.clear();
|
||||
f(&mut self.context());
|
||||
for system in self.systems.clone() {
|
||||
let Err(err) = system.on_update(&mut self.context()) else {
|
||||
continue;
|
||||
};
|
||||
println!("error occcurred updating system: {err}");
|
||||
}
|
||||
self.canvas.present();
|
||||
std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60))
|
||||
}
|
||||
self.canvas.present();
|
||||
}
|
||||
|
||||
pub fn context<'context>(&'context mut self) -> Context<'context, 'game>
|
||||
|
47
src/main.rs
47
src/main.rs
@ -1,32 +1,59 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use component_macro::Component;
|
||||
use engine::{Component, Sprite, System};
|
||||
use engine::{Sprite, System};
|
||||
use std::any::{Any, TypeId};
|
||||
use std::rc::Rc;
|
||||
mod engine;
|
||||
|
||||
use engine::Component;
|
||||
|
||||
#[derive(Component)]
|
||||
struct Player {
|
||||
sprite: Option<Sprite>,
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
struct Position(i32, i32);
|
||||
|
||||
struct Gravity;
|
||||
|
||||
impl System for Gravity {
|
||||
fn on_update(&self, ctx: &mut engine::Context) -> Result<(), engine::Error> {
|
||||
for id in ctx.entities_with_component::<Position>() {
|
||||
let Position(_, y) = ctx.entity_component::<Position>(id);
|
||||
*y += 1;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct PlayerRenderer;
|
||||
|
||||
impl System for PlayerRenderer {
|
||||
fn on_add(&self, _ctx: &mut engine::Context) {}
|
||||
|
||||
fn on_update(&self, _ctx: &mut engine::Context) {}
|
||||
fn on_update(&self, ctx: &mut engine::Context) -> Result<(), engine::Error> {
|
||||
for id in ctx.entities_with_component::<Player>() {
|
||||
let &mut Position(x, y) = ctx.entity_component::<Position>(id);
|
||||
let player = ctx.entity_component::<Player>(id);
|
||||
let sprite = player.sprite.clone().unwrap();
|
||||
ctx.draw_sprite(&sprite, x, y)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut game = engine::Game::new().unwrap();
|
||||
|
||||
let mut context = game.context();
|
||||
context.add_system(Box::new(PlayerRenderer));
|
||||
context.spawn(vec![Box::new(Player { sprite: None })]);
|
||||
|
||||
game.run(|context| {
|
||||
context.add_system(Rc::new(PlayerRenderer));
|
||||
context.add_system(Rc::new(Gravity));
|
||||
let sprite = context.load_sprite("textures/player.png").unwrap();
|
||||
context.draw_sprite(&sprite, 16, 16).unwrap();
|
||||
});
|
||||
context.spawn(vec![
|
||||
Box::new(Player {
|
||||
sprite: Some(sprite),
|
||||
}),
|
||||
Box::new(Position(16, 0)),
|
||||
]);
|
||||
game.run();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user