From 44483daa72e21d1648387caa7823d93d7df26849 Mon Sep 17 00:00:00 2001 From: Mikkel Troels Kongsted Date: Fri, 27 Mar 2026 16:15:10 +0100 Subject: [PATCH] add scene and rendering order --- game/src/engine/game.rs | 44 +++--------------- game/src/engine/math.rs | 12 ++++- game/src/engine/mod.rs | 4 +- game/src/engine/scene.rs | 59 ++++++++++++++++++++++++ game/src/engine/sdl_io.rs | 17 ++++++- game/src/engine/system.rs | 17 ------- game/src/main.rs | 97 +++++++++++++++++++++++++++++---------- 7 files changed, 166 insertions(+), 84 deletions(-) create mode 100644 game/src/engine/scene.rs delete mode 100644 game/src/engine/system.rs diff --git a/game/src/engine/game.rs b/game/src/engine/game.rs index 90f8e97..8777908 100644 --- a/game/src/engine/game.rs +++ b/game/src/engine/game.rs @@ -6,19 +6,15 @@ use std::{marker::PhantomData, time::Duration}; use super::error::Error; -pub trait Object { - fn update(&mut self, delta: Duration); - fn render(&mut self, r: &mut R); -} - -pub trait Io> { - fn run(&mut self, game: &mut Game); +pub trait Io> { + fn run(&mut self, game: &mut G); } pub trait Renderer { fn draw_rect(&mut self, pos: V2, size: V2, color: Color); fn draw_point(&mut self, pos: V2, color: Color); fn draw_line(&mut self, from: V2, to: V2, color: Color); + fn draw_triangle(&mut self, triangle: Triangle2, color: Color); fn draw_triangles(&mut self, triangles: &[Triangle2], color: Color); } @@ -36,34 +32,8 @@ pub enum Event { Exit, } -pub struct Game> { - _phantom_data: PhantomData, - objects: Vec, -} - -impl> Game { - pub fn new() -> Result { - Ok(Self { - _phantom_data: PhantomData, - objects: Vec::new(), - }) - } - - pub fn spawn(&mut self, object: O) { - self.objects.push(object); - } - - pub fn update(&mut self, delta_time: Duration) { - for object in self.objects.iter_mut() { - object.update(delta_time); - } - } - - pub fn render(&mut self, r: &mut R) { - for object in self.objects.iter_mut() { - object.render(r); - } - } - - pub fn event(&mut self, event: Event) {} +pub trait Game { + fn update(&mut self, delta_time: Duration); + fn render(&mut self, r: &mut R); + fn event(&mut self, event: Event); } diff --git a/game/src/engine/math.rs b/game/src/engine/math.rs index 9d55fb5..ca249d7 100644 --- a/game/src/engine/math.rs +++ b/game/src/engine/math.rs @@ -31,7 +31,7 @@ impl V3 { f64::sqrt(self.0.powi(2) + self.1.powi(2) + self.2.powi(2)) } - pub fn unit(&self) -> V3 { + pub fn unit(&self) -> Self { self.map(|v| v / self.len()) } @@ -39,10 +39,14 @@ impl V3 { V3(func(self.0), func(self.1), func(self.2)) } - pub fn rotate(&self, rot: V3) -> Self { + pub fn rotate(&self, rot: Self) -> Self { M3x3::new_rotate_z(rot.2) * (M3x3::new_rotate_y(rot.1) * (M3x3::new_rotate_x(rot.0) * *self)) } + + pub fn distance(&self, rhs: Self) -> f64 { + (*self - rhs).len() + } } impl Add for V3 { @@ -125,6 +129,10 @@ impl Triangle3 { pub fn middle(&self) -> V3 { (self.0 + self.1 + self.2).map(|v| v / 3.0) } + + pub fn points(&self) -> [V3; 3] { + [self.0, self.1, self.2] + } } struct M3x3([f64; 9]); diff --git a/game/src/engine/mod.rs b/game/src/engine/mod.rs index 2884b52..91f2d3f 100644 --- a/game/src/engine/mod.rs +++ b/game/src/engine/mod.rs @@ -4,14 +4,14 @@ mod error; mod game; mod math; mod r3d; +mod scene; mod sdl_io; mod shapes; -mod system; pub use error::*; pub use game::*; pub use math::*; pub use r3d::*; +pub use scene::*; pub use sdl_io::*; pub use shapes::*; -pub use system::*; diff --git a/game/src/engine/scene.rs b/game/src/engine/scene.rs new file mode 100644 index 0000000..707f325 --- /dev/null +++ b/game/src/engine/scene.rs @@ -0,0 +1,59 @@ +use crate::engine::{Color, Renderer, Shape, Triangle3, V3}; + +pub struct DrawnTriangle { + triangle: Triangle3, + outline_color: Color, + fill_color: Color, +} + +pub struct Scene { + objects: Vec, +} + +impl Scene { + pub fn new() -> Self { + Self { + objects: Vec::new(), + } + } + + pub fn render(&mut self, r: &mut R, camera: V3) { + self.objects.sort_by(|a, b| { + let a = a + .triangle + .points() + .map(|p| p.distance(camera)) + .into_iter() + .min_by(|a, b| a.total_cmp(b)) + .unwrap(); + let b = b + .triangle + .points() + .map(|p| p.distance(camera)) + .into_iter() + .min_by(|a, b| a.total_cmp(b)) + .unwrap(); + b.total_cmp(&a) + }); + + let drawn_triangles = self + .objects + .iter() + .map(|v| (v.triangle.project_2d(), v.outline_color, v.fill_color)); + for (triangle, outline_color, fill_color) in drawn_triangles { + r.draw_triangle(triangle.clone(), fill_color); + r.draw_line(triangle.0, triangle.1, outline_color); + r.draw_line(triangle.0, triangle.2, outline_color); + } + } + + pub fn draw_shape(&mut self, pos: V3, shape: &Shape, outline_color: Color, fill_color: Color) { + for triangle in shape.faces() { + self.objects.push(DrawnTriangle { + triangle: triangle.translate(pos), + outline_color, + fill_color, + }) + } + } +} diff --git a/game/src/engine/sdl_io.rs b/game/src/engine/sdl_io.rs index 227057d..d816869 100644 --- a/game/src/engine/sdl_io.rs +++ b/game/src/engine/sdl_io.rs @@ -48,7 +48,7 @@ impl SdlIo { }) } - pub fn run>(&mut self, game: &mut game::Game) { + pub fn run(&mut self, game: &mut impl game::Game) { let mut event_pump = self.sdl_context.event_pump().unwrap(); let mut time_before = Instant::now(); @@ -154,6 +154,21 @@ impl Renderer for SdlIo { .render_geometry(&vertices, None, VertexIndices::Sequential) .unwrap(); } + + fn draw_triangle(&mut self, triangle: Triangle2, color: Color) { + let vertices = [triangle.0, triangle.1, triangle.2] + .into_iter() + .map(|p| self.point_w2s(p)) + .map(|p| Vertex { + position: p.into(), + color: color.into(), + tex_coord: FPoint::new(0.0, 0.0), + }) + .collect::>(); + self.canvas + .render_geometry(&vertices, None, VertexIndices::Sequential) + .unwrap(); + } } impl From for FPoint { diff --git a/game/src/engine/system.rs b/game/src/engine/system.rs deleted file mode 100644 index 7b60dc6..0000000 --- a/game/src/engine/system.rs +++ /dev/null @@ -1,17 +0,0 @@ -use super::error::Error; - - -pub trait System { - - fn on_add(&self) -> Result<(), Error> { - Ok(()) - } - - fn on_update(&self) -> Result<(), Error> { - Ok(()) - } - - fn on_remove(&self) -> Result<(), Error> { - Ok(()) - } -} \ No newline at end of file diff --git a/game/src/main.rs b/game/src/main.rs index 961dea3..75ab0fb 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -1,51 +1,80 @@ #![allow(dead_code)] -use std::{f64, time::Duration}; +use std::time::Duration; -use crate::engine::{Color, R3d, Shape, V3}; +use crate::engine::{Color, Renderer, Scene, Shape, V3}; mod engine; mod vermiparous; -enum MyObject { - Player { pos: V3, vel: V3 }, +struct Game { + objects: Vec, } -impl engine::Object for MyObject { +impl Game { + fn new() -> Self { + Self { + objects: Vec::new(), + } + } + + fn spawn(&mut self, object: Object) { + self.objects.push(object); + } +} + +impl engine::Game for Game { + fn update(&mut self, delta_time: Duration) { + for object in &mut self.objects { + object.update(delta_time); + } + } + + fn render(&mut self, r: &mut R) { + let mut scene = Scene::new(); + for object in &mut self.objects { + object.render(&mut scene); + } + scene.render(r, V3(0.0, 0.0, -1.0)); + } + + fn event(&mut self, event: engine::Event) {} +} + +enum Object { + Player { pos: V3, vel: V3 }, + Obstacle { pos: V3, vel_z: f64 }, + Ground { pos: V3, vel_z: f64 }, +} + +impl Object { fn update(&mut self, delta_time: Duration) { match self { - MyObject::Player { pos, vel } => { + Object::Player { pos, vel } => { *pos += *vel * delta_time.as_secs_f64(); if pos.0 >= 2.1 { pos.0 = -2.0; } } + Object::Obstacle { pos, vel_z } => { + pos.2 += *vel_z * delta_time.as_secs_f64(); + } + Object::Ground { pos, vel_z } => { + pos.2 += *vel_z * delta_time.as_secs_f64(); + } } } - fn render(&mut self, r: &mut R) { + fn render(&mut self, scene: &mut Scene) { match self { - MyObject::Player { pos, .. } => { - let mut r3d = R3d::new(r); - - for z in 0..10 { - for x in -10..10 { - r3d.draw_shape( - V3(x as f64 * 0.1, -0.5, z as f64 * 0.1), - &Shape::new_plane(V3(0.1, 0.0, 0.1)), - Color::Cyan, - Color::Black, - ); - } - } - - r3d.draw_shape( + Object::Player { pos, .. } => { + scene.draw_shape( *pos + V3(0.0, 0.2, 0.0), &Shape::new_cube(V3(0.2, 0.1, 0.2)), Color::Green, Color::Black, ); - r3d.draw_shape( + scene.draw_shape( *pos + V3(-0.8, -0.2, 0.0), &Shape::new_cube(V3(0.2, 0.2, 0.2)) .translate(V3(-0.1, -0.1, -0.1)) @@ -54,19 +83,37 @@ impl engine::Object for MyObject { Color::Black, ); } + Object::Obstacle { pos, vel_z } => todo!(), + Object::Ground { pos, .. } => { + for z in 0..10 { + for x in -10..10 { + scene.draw_shape( + V3(x as f64 * 0.1 + pos.0, pos.1, z as f64 * 0.1 + pos.2), + &Shape::new_plane(V3(0.1, 0.0, 0.1)), + Color::Cyan, + Color::Black, + ); + } + } + } } } } fn main() -> Result<(), Box> { let mut sdl_io = engine::SdlIo::new()?; - let mut game = engine::Game::::new()?; + let mut game = Game::new(); - let player = MyObject::Player { + let player = Object::Player { pos: V3(-1.0, -0.1, 0.0), vel: V3(0.4, 0.0, 0.0), }; game.spawn(player); + let ground = Object::Ground { + pos: V3(0.0, -0.3, -0.5), + vel_z: -0.1, + }; + game.spawn(ground); sdl_io.run(&mut game); Ok(())