diff --git a/src/engine.rs b/src/engine.rs index c29f59b..b102913 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -1,10 +1,13 @@ -use self::objs::{obj_traits::MovingObject, World}; +const GAME_SIZE: (u32, u32) = (1200, 800); use std::{ + collections::HashMap, num::NonZeroU32, process, rc::Rc, time::{Duration, Instant}, }; + +use softbuffer::Buffer; use winit::{ dpi::PhysicalSize, event::{Event, KeyEvent, StartCause, WindowEvent}, @@ -14,16 +17,9 @@ use winit::{ window::WindowBuilder, }; -pub mod objs; -mod render; -mod timer; +use self::objs::{MovingObject, World}; -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); +type RenderFn = fn(&mut render::RenderCtx<'_, '_>, &mut World, &GameTimer); // core game engine struct pub struct Engine { event_loop: EventLoop<()>, @@ -71,7 +67,7 @@ impl Engine { let mut surface = softbuffer::Surface::new(&context, window.window_handle().unwrap()).unwrap(); - let mut timer = timer::GameTimer::new(); + let mut timer = GameTimer::new(); event_loop .run(|event, elwt| { @@ -85,44 +81,6 @@ impl Engine { Event::NewEvents(StartCause::ResumeTimeReached { .. }) => { window.request_redraw(); } - Event::WindowEvent { - window_id, - event: WindowEvent::Resized(PhysicalSize { width, height }), - } => { - if window_id == window.id() { - if let (Some(width), Some(height)) = - (NonZeroU32::new(width), NonZeroU32::new(height)) - { - surface.resize(width, height).unwrap(); - let mut buffer = surface.buffer_mut().unwrap(); - buffer.fill(BG); - - let mut ctx = - render::RenderCtx::new(buffer, (width, height), GAME_SIZE); - - // top - ctx.rect(0, 0, GAME_SIZE.0, BORDER_WIDTH, FG); - // left - ctx.rect( - 0, - BORDER_WIDTH, - BORDER_WIDTH, - GAME_SIZE.1 - BORDER_WIDTH * 2, - FG, - ); - // right - ctx.rect( - GAME_SIZE.0 - BORDER_WIDTH, - BORDER_WIDTH, - BORDER_WIDTH, - GAME_SIZE.1 - BORDER_WIDTH * 2, - FG, - ); - // bottom - ctx.rect(0, GAME_SIZE.1 - BORDER_WIDTH, GAME_SIZE.0, 10, FG); - } - } - } Event::WindowEvent { window_id, event: WindowEvent::RedrawRequested, @@ -133,7 +91,7 @@ impl Engine { (NonZeroU32::new(size.width), NonZeroU32::new(size.height)) } { surface.resize(width, height).unwrap(); - let buffer = surface.buffer_mut().unwrap(); + let mut buffer = surface.buffer_mut().unwrap(); let mut ctx = render::RenderCtx::new(buffer, (width, height), GAME_SIZE); @@ -176,3 +134,216 @@ 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; + + 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, 0xffffff); + } + } + + 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, 0x000000); + self.display(ctx); + } + } +} diff --git a/src/engine/objs.rs b/src/engine/objs.rs deleted file mode 100644 index 3199951..0000000 --- a/src/engine/objs.rs +++ /dev/null @@ -1,38 +0,0 @@ -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 deleted file mode 100644 index 9766c6a..0000000 --- a/src/engine/objs/geometry.rs +++ /dev/null @@ -1,22 +0,0 @@ -#[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 deleted file mode 100644 index dabd454..0000000 --- a/src/engine/objs/obj_traits.rs +++ /dev/null @@ -1,38 +0,0 @@ -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 deleted file mode 100644 index 32c1748..0000000 --- a/src/engine/objs/primitive_shapes.rs +++ /dev/null @@ -1,79 +0,0 @@ -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 a0b4492..2f62bf6 100644 --- a/src/engine/render.rs +++ b/src/engine/render.rs @@ -6,6 +6,8 @@ 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>>, @@ -56,9 +58,6 @@ 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 deleted file mode 100644 index 46dbf98..0000000 --- a/src/engine/timer.rs +++ /dev/null @@ -1,45 +0,0 @@ -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 1e11bf1..7cb82eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,16 +1,19 @@ use std::rc::Rc; -use engine::Engine; +use engine::{ + objs::{MovingRect, Object, Rect}, + Engine, +}; fn main() { let mut engine = Engine::new(); - // let _ = engine.insert_into_world(Rc::new(MovingRect::new(0, 0, 50, 100))); + let _ = engine.insert_into_world(Rc::new(MovingRect::new(0, 0, 50, 100))); engine .set_render_fn(|ctx, world, timer| { - // println!("t: {}", timer.game_time_passed()); - // let obj = Rc::get_mut(world.get_mut(0)).unwrap(); - // obj.move_obj(1, 0); - // obj.draw_move(ctx) + println!("t: {}", timer.game_time_passed()); + let obj = Rc::get_mut(world.get_mut(0)).unwrap(); + obj.move_obj(1, 0); + obj.draw_move(ctx) // Rect::square((timer.game_time_passed() * 20.) as u32, 0, 200).display(ctx); }) .run();