From 11f9fecba1a19875f91d95fe85efc819e0c9c4c4 Mon Sep 17 00:00:00 2001 From: Schrottkatze Date: Fri, 23 Feb 2024 08:37:13 +0100 Subject: [PATCH] basic refactoring --- src/engine.rs | 236 ++-------------------------- src/engine/objs.rs | 38 +++++ src/engine/objs/geometry.rs | 22 +++ src/engine/objs/obj_traits.rs | 38 +++++ src/engine/objs/primitive_shapes.rs | 79 ++++++++++ src/engine/render.rs | 5 +- src/engine/timer.rs | 45 ++++++ src/main.rs | 5 +- 8 files changed, 238 insertions(+), 230 deletions(-) create mode 100644 src/engine/objs.rs create mode 100644 src/engine/objs/geometry.rs create mode 100644 src/engine/objs/obj_traits.rs create mode 100644 src/engine/objs/primitive_shapes.rs create mode 100644 src/engine/timer.rs diff --git a/src/engine.rs b/src/engine.rs index 4872bbd..c29f59b 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -1,16 +1,10 @@ -const GAME_SIZE: (u32, u32) = (1200, 800); -const BORDER_WIDTH: u32 = 10; -const FG: u32 = 0xebdbb2; -const BG: u32 = 0x282828; +use self::objs::{obj_traits::MovingObject, World}; use std::{ - collections::HashMap, num::NonZeroU32, process, rc::Rc, time::{Duration, Instant}, }; - -use softbuffer::Buffer; use winit::{ dpi::PhysicalSize, event::{Event, KeyEvent, StartCause, WindowEvent}, @@ -20,9 +14,16 @@ use winit::{ window::WindowBuilder, }; -use self::objs::{MovingObject, World}; +pub mod objs; +mod render; +mod timer; -type RenderFn = fn(&mut render::RenderCtx<'_, '_>, &mut World, &GameTimer); +const GAME_SIZE: (u32, u32) = (1200, 800); +const BORDER_WIDTH: u32 = 10; +const FG: u32 = 0xebdbb2; +const BG: u32 = 0x282828; + +type RenderFn = fn(&mut render::RenderCtx<'_, '_>, &mut World, &timer::GameTimer); // core game engine struct pub struct Engine { event_loop: EventLoop<()>, @@ -70,7 +71,7 @@ impl Engine { let mut surface = softbuffer::Surface::new(&context, window.window_handle().unwrap()).unwrap(); - let mut timer = GameTimer::new(); + let mut timer = timer::GameTimer::new(); event_loop .run(|event, elwt| { @@ -132,7 +133,7 @@ impl Engine { (NonZeroU32::new(size.width), NonZeroU32::new(size.height)) } { surface.resize(width, height).unwrap(); - let mut buffer = surface.buffer_mut().unwrap(); + let buffer = surface.buffer_mut().unwrap(); let mut ctx = render::RenderCtx::new(buffer, (width, height), GAME_SIZE); @@ -175,216 +176,3 @@ impl Engine { process::exit(0); } } - -pub struct GameTimer { - game_start: Instant, - last_frame: Instant, - stopwatches: HashMap, -} - -impl GameTimer { - pub fn new() -> Self { - Self { - game_start: Instant::now(), - last_frame: Instant::now(), - stopwatches: HashMap::new(), - } - } - - pub fn frame_update(&mut self) { - self.last_frame = Instant::now() - } - - pub fn delta_t(&self) -> f32 { - Instant::now().duration_since(self.last_frame).as_secs_f32() - } - - pub fn game_time_passed(&self) -> f32 { - Instant::now().duration_since(self.game_start).as_secs_f32() - } - - pub fn start_stopwatch(&mut self, name: impl ToString) { - let _ = self.stopwatches.insert(name.to_string(), Instant::now()); - } - - pub fn get_stopwatch_time(&self, name: &str) -> Option { - self.stopwatches - .get(name) - .map(|start_time| Instant::now().duration_since(*start_time).as_secs_f32()) - } - - pub fn delete_stopwatch(&mut self, name: &str) { - let _ = self.stopwatches.remove(name); - } -} - -mod render; - -pub mod objs { - use std::rc::Rc; - - use super::{render::RenderCtx, BG, FG}; - - pub struct World { - objects: Vec>, - } - - impl World { - pub fn new() -> Self { - Self { - objects: Vec::new(), - } - } - - pub fn insert(&mut self, obj: Rc) -> usize { - self.objects.push(obj); - self.objects.len() - 1 - } - - pub fn get(&self, i: usize) -> Rc { - self.objects[i].clone() - } - - pub fn get_mut(&mut self, i: usize) -> &mut Rc { - &mut self.objects[i] - } - - pub fn draw_all(&self, ctx: &mut RenderCtx<'_, '_>) { - self.objects.iter().for_each(|obj| obj.display(ctx)) - } - } - - #[derive(Clone, Copy, Debug, Eq, PartialEq)] - pub struct Rect { - pos: Position, - size: Size, - } - - impl Rect { - pub fn new(x: u32, y: u32, height: u32, width: u32) -> Self { - Self { - pos: Position::new(x, y), - size: Size::new(width, height), - } - } - - pub fn square(x: u32, y: u32, size: u32) -> Self { - Self { - pos: Position::new(x, y), - size: Size::new(size, size), - } - } - } - - impl Object for Rect { - fn position(&self) -> Position { - self.pos - } - - fn size(&self) -> Size { - self.size - } - } - - #[derive(Clone, Copy, Debug, Eq, PartialEq)] - pub struct MovingRect { - prev_pos: Position, - current: Rect, - } - - impl MovingRect { - pub fn new(x: u32, y: u32, height: u32, width: u32) -> Self { - Self { - prev_pos: Position::new(x, y), - current: Rect::new(x, y, height, width), - } - } - - pub fn square(x: u32, y: u32, size: u32) -> Self { - Self { - prev_pos: Position::new(x, y), - current: Rect::square(x, y, size), - } - } - } - - impl Object for MovingRect { - fn position(&self) -> Position { - self.current.position() - } - - fn size(&self) -> Size { - self.current.size() - } - } - - impl MovingObject for MovingRect { - fn previous_pos(&self) -> Position { - self.prev_pos - } - - fn update_pos(&mut self, x: u32, y: u32) { - self.prev_pos = self.current.pos; - self.current.pos = Position::new(x, y); - } - } - - #[derive(Clone, Copy, Debug, Eq, PartialEq)] - pub struct Position { - x: u32, - y: u32, - } - - impl Position { - pub fn new(x: u32, y: u32) -> Self { - Self { x, y } - } - } - - #[derive(Clone, Copy, Debug, Eq, PartialEq)] - pub struct Size { - width: u32, - height: u32, - } - - impl Size { - pub fn new(width: u32, height: u32) -> Self { - Self { width, height } - } - } - - pub trait Object { - fn position(&self) -> Position; - fn size(&self) -> Size; - fn display(&self, ctx: &mut RenderCtx<'_, '_>) { - let Position { x, y } = self.position(); - let Size { width, height } = self.size(); - ctx.rect(x, y, width, height, FG); - } - } - - pub trait MovingObject: Object { - fn previous_pos(&self) -> Position; - fn update_pos(&mut self, x: u32, y: u32); - fn move_obj(&mut self, x: i32, y: i32) { - let Position { x: cur_x, y: cur_y } = self.position(); - - self.update_pos( - cur_x.saturating_add_signed(x), - cur_y.saturating_add_signed(y), - ) - } - - // TODO: damage - fn draw_move(&self, ctx: &mut RenderCtx<'_, '_>) { - let Position { - x: prev_x, - y: prev_y, - } = self.previous_pos(); - let Size { width, height } = self.size(); - - ctx.rect(prev_x, prev_y, width, height, BG); - self.display(ctx); - } - } -} diff --git a/src/engine/objs.rs b/src/engine/objs.rs new file mode 100644 index 0000000..3199951 --- /dev/null +++ b/src/engine/objs.rs @@ -0,0 +1,38 @@ +use std::rc::Rc; + +use self::obj_traits::MovingObject; + +use super::{render::RenderCtx, BG, FG}; + +pub mod geometry; +pub mod obj_traits; +pub mod primitive_shapes; + +pub struct World { + objects: Vec>, +} + +impl World { + pub fn new() -> Self { + Self { + objects: Vec::new(), + } + } + + pub fn insert(&mut self, obj: Rc) -> usize { + self.objects.push(obj); + self.objects.len() - 1 + } + + pub fn get(&self, i: usize) -> Rc { + self.objects[i].clone() + } + + pub fn get_mut(&mut self, i: usize) -> &mut Rc { + &mut self.objects[i] + } + + pub fn draw_all(&self, ctx: &mut RenderCtx<'_, '_>) { + self.objects.iter().for_each(|obj| obj.display(ctx)) + } +} diff --git a/src/engine/objs/geometry.rs b/src/engine/objs/geometry.rs new file mode 100644 index 0000000..9766c6a --- /dev/null +++ b/src/engine/objs/geometry.rs @@ -0,0 +1,22 @@ +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct Position { + pub x: u32, + pub y: u32, +} + +impl Position { + pub fn new(x: u32, y: u32) -> Self { + Self { x, y } + } +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct Size { + pub width: u32, + pub height: u32, +} +impl Size { + pub fn new(width: u32, height: u32) -> Self { + Self { width, height } + } +} diff --git a/src/engine/objs/obj_traits.rs b/src/engine/objs/obj_traits.rs new file mode 100644 index 0000000..dabd454 --- /dev/null +++ b/src/engine/objs/obj_traits.rs @@ -0,0 +1,38 @@ +use crate::engine::{render::RenderCtx, BG, FG}; + +use super::geometry::{Position, Size}; + +pub trait Object { + fn position(&self) -> Position; + fn size(&self) -> Size; + fn display(&self, ctx: &mut RenderCtx<'_, '_>) { + let Position { x, y } = self.position(); + let Size { width, height } = self.size(); + ctx.rect(x, y, width, height, FG); + } +} + +pub trait MovingObject: Object { + fn previous_pos(&self) -> Position; + fn update_pos(&mut self, x: u32, y: u32); + fn move_obj(&mut self, x: i32, y: i32) { + let Position { x: cur_x, y: cur_y } = self.position(); + + self.update_pos( + cur_x.saturating_add_signed(x), + cur_y.saturating_add_signed(y), + ) + } + + // TODO: damage + fn draw_move(&self, ctx: &mut RenderCtx<'_, '_>) { + let Position { + x: prev_x, + y: prev_y, + } = self.previous_pos(); + let Size { width, height } = self.size(); + + ctx.rect(prev_x, prev_y, width, height, BG); + self.display(ctx); + } +} diff --git a/src/engine/objs/primitive_shapes.rs b/src/engine/objs/primitive_shapes.rs new file mode 100644 index 0000000..32c1748 --- /dev/null +++ b/src/engine/objs/primitive_shapes.rs @@ -0,0 +1,79 @@ +use super::{ + geometry::{Position, Size}, + obj_traits::{MovingObject, Object}, +}; + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct Rect { + pos: Position, + size: Size, +} + +impl Rect { + pub fn new(x: u32, y: u32, height: u32, width: u32) -> Self { + Self { + pos: Position::new(x, y), + size: Size::new(width, height), + } + } + + pub fn square(x: u32, y: u32, size: u32) -> Self { + Self { + pos: Position::new(x, y), + size: Size::new(size, size), + } + } +} + +impl Object for Rect { + fn position(&self) -> Position { + self.pos + } + + fn size(&self) -> Size { + self.size + } +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct MovingRect { + prev_pos: Position, + current: Rect, +} + +impl MovingRect { + pub fn new(x: u32, y: u32, height: u32, width: u32) -> Self { + Self { + prev_pos: Position::new(x, y), + current: Rect::new(x, y, height, width), + } + } + + pub fn square(x: u32, y: u32, size: u32) -> Self { + Self { + prev_pos: Position::new(x, y), + current: Rect::square(x, y, size), + } + } +} + +impl Object for MovingRect { + fn position(&self) -> Position { + self.current.position() + } + + fn size(&self) -> Size { + self.current.size() + } +} + +impl MovingObject for MovingRect { + fn previous_pos(&self) -> Position { + self.prev_pos + } + + fn update_pos(&mut self, x: u32, y: u32) { + self.prev_pos = self.current.pos; + self.current.pos = Position::new(x, y); + } +} diff --git a/src/engine/render.rs b/src/engine/render.rs index 2f62bf6..a0b4492 100644 --- a/src/engine/render.rs +++ b/src/engine/render.rs @@ -6,8 +6,6 @@ use winit::raw_window_handle::DisplayHandle; use softbuffer::Buffer; -use super::objs::Object; - // render context pub struct RenderCtx<'buf, 'win> { pub(crate) buffer: Buffer<'buf, DisplayHandle<'win>, WindowHandle<'win>>, @@ -58,6 +56,9 @@ impl<'buf, 'win> RenderCtx<'buf, 'win> { } } + /// draw a rectangle in a context + /// + /// this method limits overflows etc pub fn rect(&mut self, x: u32, y: u32, width: u32, height: u32, color: u32) { if x >= self.context_size.0 || y >= self.context_size.1 || width == 0 || height == 0 { } else { diff --git a/src/engine/timer.rs b/src/engine/timer.rs new file mode 100644 index 0000000..46dbf98 --- /dev/null +++ b/src/engine/timer.rs @@ -0,0 +1,45 @@ +use std::collections::HashMap; + +use std::time::Instant; + +pub struct GameTimer { + pub(crate) game_start: Instant, + pub(crate) last_frame: Instant, + pub(crate) stopwatches: HashMap, +} + +impl GameTimer { + pub fn new() -> Self { + Self { + game_start: Instant::now(), + last_frame: Instant::now(), + stopwatches: HashMap::new(), + } + } + + pub fn frame_update(&mut self) { + self.last_frame = Instant::now() + } + + pub fn delta_t(&self) -> f32 { + Instant::now().duration_since(self.last_frame).as_secs_f32() + } + + pub fn game_time_passed(&self) -> f32 { + Instant::now().duration_since(self.game_start).as_secs_f32() + } + + pub fn start_stopwatch(&mut self, name: impl ToString) { + let _ = self.stopwatches.insert(name.to_string(), Instant::now()); + } + + pub fn get_stopwatch_time(&self, name: &str) -> Option { + self.stopwatches + .get(name) + .map(|start_time| Instant::now().duration_since(*start_time).as_secs_f32()) + } + + pub fn delete_stopwatch(&mut self, name: &str) { + let _ = self.stopwatches.remove(name); + } +} diff --git a/src/main.rs b/src/main.rs index 9ff4dde..1e11bf1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,6 @@ use std::rc::Rc; -use engine::{ - objs::{MovingRect, Object, Rect}, - Engine, -}; +use engine::Engine; fn main() { let mut engine = Engine::new();