From b924d38cd88178ce05b1de5c6d5ea0b64aaf12b0 Mon Sep 17 00:00:00 2001 From: DanielMowitz Date: Thu, 5 Mar 2020 23:42:01 +0100 Subject: [PATCH] Some updates that happened while working with the lib. --- Cargo.lock | 2 + src/action.rs | 12 +++--- src/bin.rs | 35 ++++++++-------- src/button.rs | 22 ++++++---- src/{dispatcher/mod.rs => dispatcher.rs} | 11 ++--- src/img.rs | 16 +++++--- src/lib.rs | 5 +-- src/renderer.rs | 50 ++++++++++++++++------- src/resources/test_img.u4i | Bin 11 -> 0 bytes src/scene_manager.rs | 13 +++--- src/sprite.rs | 31 +++++++------- src/store.rs | 1 - src/{test_obj.rs => test_object.rs} | 14 +++---- src/tests.rs | 8 ++-- 14 files changed, 123 insertions(+), 97 deletions(-) rename src/{dispatcher/mod.rs => dispatcher.rs} (95%) delete mode 100644 src/resources/test_img.u4i rename src/{test_obj.rs => test_object.rs} (83%) diff --git a/Cargo.lock b/Cargo.lock index 2e180af..3eab740 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "autocfg" version = "0.1.2" diff --git a/src/action.rs b/src/action.rs index 1f4eb40..38a4a9f 100644 --- a/src/action.rs +++ b/src/action.rs @@ -1,24 +1,24 @@ -use std::any::Any; - use sdl2::mouse::MouseButton; use super::img::Img; +use sdl2::keyboard::{Scancode}; /// An Action in the Flux pattern sense. Has a type and a payload. /// /// All communication between the stores happen through these babies. They are sent to the /// dispatcher which sends them to every store that wants to hear of actions of their type. pub enum Action { - AddImgToCanvasAction(u8, u8, Img), + AddImgToCanvasAction(u32, u32, Img), DrawAction(bool), UpdateAction, - SendFrameAction, + SendFrameAction(u32, u32, u32), EndFrameAction, StartAction, MenuAction(MenuSubAction), QuitAction, EmptyAction, TestAction(u8), + KeyboardAction(Scancode), } /// Similar to the action Enum. Only meant for use in menu states. @@ -26,7 +26,7 @@ pub enum MenuSubAction { ChangeMenuStateAction, WaitForInputAction, DrawAction, - AddImgToCanvasAction(u8, u8, Img), - ClickAction(i32, i32, MouseButton), + AddImgToCanvasAction(u32, u32, Img), + ClickAction(i32, i32, MouseButton, u32), QuitAction, } diff --git a/src/bin.rs b/src/bin.rs index 0202eca..c153062 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -1,33 +1,30 @@ extern crate frame; extern crate sdl2; -use std::fs::File; +use frame::scene_manager::SceneManager; -use frame::img::Img; +mod main_menu; +mod space_ship; +mod light_path; -/// An example use of the framework fn main() { - let mut example_img = frame::img::Img::new_from_u8(4, vec![]); - match File::open("./resources/test_img.u4i") { - Ok(f) => { - example_img = Img::new_from_File(f); - } - Err(e) => { - print!("{}", e); - } - } + let mut ship = space_ship::Spaceship::new(); + let mut renderer = frame::renderer::Renderer::new(512, 512, None); - let example_sprite = frame::sprite::Sprite::new((0, 0), vec![example_img], vec![(0, 1)], 60.0); - let mut example_game_obj = frame::example_obj::ExampleObj::new(example_sprite); - let mut example_renderer = frame::renderer::Renderer::new(255, 255, None); - let mut example_disp = frame::dispatcher::Dispatcher::new(1.0 / 60.0); + let mut menu = main_menu::MainMenu::new(); + let mut scene_manager = SceneManager::new(); + + scene_manager.add_scenes(vec![&mut menu]); + + let mut disp = frame::dispatcher::Dispatcher::new(1.0 / 60.0); frame::game_loop( - &mut example_disp, + &mut disp, vec![ - &mut example_game_obj, - &mut example_renderer, + &mut ship, + &mut renderer, + &mut scene_manager, ], ); } diff --git a/src/button.rs b/src/button.rs index bcd0ce9..587bacd 100644 --- a/src/button.rs +++ b/src/button.rs @@ -4,15 +4,14 @@ use super::sprite::Sprite; /// A clickable button. pub struct Button { sprite: Sprite, - pos: (i32, i32), click_fn: Box MenuSubAction>, } impl Button { pub fn send_frame(&self) -> MenuSubAction { MenuSubAction::AddImgToCanvasAction( - self.pos.0.clone() as u8, - self.pos.1.clone() as u8, + self.sprite.get_pos().0, + self.sprite.get_pos().1, self.sprite.get_current_frame(), ) } @@ -23,19 +22,26 @@ impl Button { } /// Calls the function closure when a click is detected upon the button. - pub fn check_click(&self, x: &i32, y: &i32) -> Option { - if &self.pos.0 < x || x < &(&self.pos.0 + self.sprite.get_width()) { - if &self.pos.1 < y || y < &(&self.pos.1 + self.sprite.get_height()) { + pub fn check_click(&self, x: u32, y: u32, px_size: u32) -> Option { + + let sprite_x = &self.sprite.get_pos().0 * px_size; + let sprite_y = &self.sprite.get_pos().1 * px_size; + + println!("cx:{}, cy:{}", sprite_x, sprite_y); + println!("cx:{}, cy:{}", x, y); + println!("cx:{}, cy:{}", sprite_x + self.sprite.get_width() * px_size, sprite_y + self.sprite.get_height() * px_size); + + if sprite_x < x && x < sprite_x + self.sprite.get_width() * px_size { + if sprite_y < y && y < sprite_y + self.sprite.get_height() * px_size { return Some((self.click_fn)()); } } return None; } - pub fn new(sprite: Sprite, pos: (i32, i32), click_fn: Box MenuSubAction>) -> Self { + pub fn new(sprite: Sprite, click_fn: Box MenuSubAction>) -> Self { Self { sprite, - pos, click_fn, } } diff --git a/src/dispatcher/mod.rs b/src/dispatcher.rs similarity index 95% rename from src/dispatcher/mod.rs rename to src/dispatcher.rs index 1df853e..d496faf 100644 --- a/src/dispatcher/mod.rs +++ b/src/dispatcher.rs @@ -1,8 +1,6 @@ use std::collections::VecDeque; use std::time::Instant; -use sdl2::Sdl; - use action::Action::MenuAction; use super::action::*; @@ -106,7 +104,7 @@ impl<'a> Dispatcher<'a> { * order at the same time. */ Some(in_reference) => { - self.dt = self.current_stack_start_time.elapsed().as_float_secs(); + self.dt = self.current_stack_start_time.elapsed().as_secs_f64(); match in_reference.receive_action(&in_action, &self.dt) { ReceiveActionReturnOption::NewAction(out_action_vec, add_to_secondary, out_reference) => { if add_to_secondary { @@ -136,11 +134,11 @@ impl<'a> Dispatcher<'a> { return true; } - /// Used in the sipatch function. + /// Used in the dispatch function. /// returns the appropriate action from the appropriate Stack. fn get_in_action(&mut self) -> Option { if self.use_secondary { - if self.current_stack_start_time.elapsed().as_float_secs() >= self.max_stack_time { + if self.current_stack_start_time.elapsed().as_secs_f64() >= self.max_stack_time { return Some(Action::EndFrameAction); } else { match self.secondary_action_queue.pop_front() { @@ -170,7 +168,7 @@ impl<'a> Dispatcher<'a> { } } None => { - if self.current_stack_start_time.elapsed().as_float_secs() >= self.max_stack_time { + if self.current_stack_start_time.elapsed().as_secs_f64() >= self.max_stack_time { return Some(Action::EndFrameAction); } else { self.use_secondary = true; @@ -202,7 +200,6 @@ impl<'a> Dispatcher<'a> { } } } - return None; } ///Adds an action to the primary stack. diff --git a/src/img.rs b/src/img.rs index 0ac1434..8b370e4 100644 --- a/src/img.rs +++ b/src/img.rs @@ -1,4 +1,3 @@ -use std::fmt::Error; use std::fs::File; use std::io::Read; @@ -12,7 +11,7 @@ pub struct Img { impl Img { /// Creates new Img from u8 vector. - pub fn new_from_u8(mut width: usize, pixels: Vec) -> Self { + pub fn new_from_u8(width: usize, pixels: Vec) -> Self { Self { width, current_px: 0, @@ -21,12 +20,15 @@ impl Img { } /// Reads file into Img. - pub fn new_from_File(mut f: File) -> Self { + pub fn new_from_file(mut f: File) -> Self { let mut width = 0; let mut pixels = vec![]; let mut buf: Vec = vec![]; - f.read_to_end(&mut buf); + match f.read_to_end(&mut buf) { + Ok(_) => {}, + Err(e) => eprintln!("Could not open image buffer:{}", e), + } if buf.len() < 4 { return Self { @@ -38,7 +40,7 @@ impl Img { let mut ctr = 0; - for (num) in buf.iter() { + for num in buf.iter() { if ctr >= 4 { pixels.push(*num); } else { @@ -63,6 +65,10 @@ impl Img { pub fn get_width(&self) -> &usize { &self.width } + + /// Returns length of pixel vector + pub fn get_length(&self) -> usize { *&self.pixels.len().clone() } + } impl Iterator for Img { diff --git a/src/lib.rs b/src/lib.rs index ee31eff..f68f186 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,8 +8,7 @@ pub mod action; pub mod store; pub mod renderer; pub mod sprite; -pub mod test_obj; -pub mod example_obj; +pub mod test_object; pub mod img; pub mod button; pub mod scene_manager; @@ -18,7 +17,7 @@ pub mod scene_manager; mod tests; /// "Front-end"-function of the dispatcher -pub fn game_loop<'a>(mut disp: & mut dispatcher::Dispatcher<'a>, store_refs: Vec<&'a mut store::Store<'a>>) { +pub fn game_loop<'a>(disp: & mut dispatcher::Dispatcher<'a>, store_refs: Vec<&'a mut store::Store<'a>>) { disp.enter_refs(store_refs); diff --git a/src/renderer.rs b/src/renderer.rs index ee8240a..6f8ef63 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -1,16 +1,13 @@ extern crate sdl2; -use std::string; use std::thread::sleep; -use std::time::{Duration, Instant}; +use std::time::Duration; use std::vec::Vec; use sdl2::event::Event; use sdl2::EventPump; use sdl2::keyboard::Keycode; use sdl2::pixels::Color; -use sdl2::pixels::PixelFormat; -use sdl2::pixels::PixelFormatEnum; use sdl2::rect::Rect; use sdl2::render::Canvas; use sdl2::Sdl; @@ -20,8 +17,6 @@ use sdl2::VideoSubsystem; use action::MenuSubAction; use super::action::Action; -use super::dispatcher::Dispatcher; -use super::dispatcher::MenuState; use super::img::Img; use super::store::ReceiveActionReturnOption; use super::store::Store; @@ -33,6 +28,7 @@ pub struct Renderer { video_subsystem: VideoSubsystem, canvas: Canvas, color_space: [Color; 15], + pixel_size: u32, } impl Renderer { @@ -80,9 +76,11 @@ impl Renderer { video_subsystem, canvas, color_space, - }; + pixel_size: 8, + } } + #[test] pub fn test(&mut self, img: Img) -> bool { print!("This is the Test function!\n"); self.canvas.set_draw_color(Color::RGB(0, 0, 0)); @@ -104,7 +102,7 @@ impl Renderer { } ///Adds an image to the canvas in the desired location - pub fn add_to_canvas(&mut self, x: u8, y: u8, i: Img) { + pub fn add_to_canvas(&mut self, x: u32, y: u32, i: Img) { let mask: u8 = 0b00001111; let alpha_value: u8 = 15; @@ -125,9 +123,17 @@ impl Renderer { right order*/ let x_i32 = (x_img * 2) as i32 + x as i32 + (1 - i); let y_i32 = y_img as i32 + y as i32; - let drawing_rect = Rect::new(8 * x_i32, 8 * y_i32, 8, 8); - self.canvas.fill_rect(drawing_rect); - self.canvas.draw_rect(drawing_rect); + let drawing_rect = Rect::new(self.pixel_size as i32 * x_i32, self.pixel_size as i32 * y_i32, self.pixel_size, self.pixel_size); + + match self.canvas.fill_rect(drawing_rect) { + Ok(_) => {}, + Err(e) => eprintln!("Could not fill shape:{}", e), + } + + match self.canvas.draw_rect(drawing_rect) { + Ok(_) => {}, + Err(e) => eprintln!("Could not draw shape:{}", e), + } } } } @@ -149,6 +155,13 @@ impl Renderer { self.color_space = space; } + pub fn get_canvas_size(&mut self) -> (u32, u32) { + match self.canvas.output_size() { + Ok(r) => (r.0, r.1), + _ => (0, 0) + } + } + /// This function is used for all user input (i.e. Mouse, Keyboard...) fn handle_inputs(&mut self) -> Vec { let mut out_vec: Vec = vec![]; @@ -160,7 +173,13 @@ impl Renderer { Event::KeyDown { keycode: Some(Keycode::Escape), .. } => { out_vec.push(Action::MenuAction(MenuSubAction::ChangeMenuStateAction)); } - //todo: maybe implement mouseaction here too + Event::KeyDown { scancode, ..} => { + match scancode { + Some(c) => out_vec.push(Action::KeyboardAction(c)), + None => {} + } + } + //maybe mouseaction will be implemented here too some day… _ => {} }; }; @@ -181,7 +200,7 @@ impl Renderer { x, y, timestamp, window_id, which, mouse_btn, clicks } => { - out_vec.push(Action::MenuAction(MenuSubAction::ClickAction(x, y, mouse_btn))); + out_vec.push(Action::MenuAction(MenuSubAction::ClickAction(x, y, mouse_btn, self.pixel_size))); } _ => {} }; @@ -205,9 +224,10 @@ impl<'a> Store<'a> for Renderer { return ReceiveActionReturnOption::NoNewAction(self); } &Action::EndFrameAction => { + let size = self.get_canvas_size(); let mut out_vec = self.handle_inputs(); out_vec.push(Action::UpdateAction); - out_vec.push(Action::SendFrameAction); + out_vec.push(Action::SendFrameAction(size.0, size.1, self.pixel_size)); out_vec.push(Action::DrawAction(true)); return ReceiveActionReturnOption::NewAction( out_vec, @@ -239,3 +259,5 @@ impl<'a> Store<'a> for Renderer { } } } + +//todo: render layers? \ No newline at end of file diff --git a/src/resources/test_img.u4i b/src/resources/test_img.u4i deleted file mode 100644 index 44f5fa62f2a3e356952d4b712e86e03f7839d979..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11 ScmZQzU|?ZXc1`bGeHH)*w*uAx diff --git a/src/scene_manager.rs b/src/scene_manager.rs index 195038a..d230918 100644 --- a/src/scene_manager.rs +++ b/src/scene_manager.rs @@ -3,6 +3,7 @@ use sdl2::mouse::MouseButton; use action::{Action, MenuSubAction}; use store; + pub trait Scene<'a> { //elements: vec fn receive_menu_sub_action(&mut self, sub_action: &super::action::MenuSubAction) -> super::store::ReceiveMSAReturnOption; @@ -26,15 +27,15 @@ impl<'a> Scene<'a> for MinimalScene { super::action::MenuSubAction::DrawAction => { return super::store::ReceiveMSAReturnOption::NewAction( vec!( - self.button.send_frame(), //todo:hier testen + self.button.send_frame(), ), self, ); } - super::action::MenuSubAction::ClickAction(x, y, mouse_btn) => { + super::action::MenuSubAction::ClickAction(x, y, mouse_btn, pix_size) => { match mouse_btn { - MouseButton::Left => match self.button.check_click(x, y) { + MouseButton::Left => match self.button.check_click(*x as u32, *y as u32, pix_size.clone()) { Some(msa) => return super::store::ReceiveMSAReturnOption::NewAction(vec![msa], self), None => return super::store::ReceiveMSAReturnOption::NoNewAction(self) }, @@ -52,7 +53,7 @@ impl<'a> Scene<'a> for MinimalScene { /// Very similar to the dispatcher, the SceneManager supervises menus. pub struct SceneManager<'a> { scenes: Option>>>, - //For an explaination of this look below. todo:better comment lol + // Works exactly lke the dispatchers store refs. current_scene: usize, } @@ -110,7 +111,7 @@ impl<'a> super::store::Store<'a> for SceneManager<'a> { } match self.scenes.take() { - //Psyche! Look at the similar function in dispatcher. + //As noted above, to understand this better look at the similar function in dispatcher. Some(mut local_scenes) => { for index in 0..local_scenes.len() { match local_scenes[index].take() { @@ -135,7 +136,7 @@ impl<'a> super::store::Store<'a> for SceneManager<'a> { super::store::ReceiveActionReturnOption::NewAction(out_actions, false, self) } None => { - panic!("No scenes yet ( ͡° ͜ʖ ͡°)"); + eprintln!("No scenes yet ( ͡° ͜ʖ ͡°)"); super::store::ReceiveActionReturnOption::NoNewAction(self) } } diff --git a/src/sprite.rs b/src/sprite.rs index fbf1911..cae2cb2 100644 --- a/src/sprite.rs +++ b/src/sprite.rs @@ -1,15 +1,11 @@ use std::fs::File; use std::io::Read; -use super::action::Action; -use super::dispatcher::Dispatcher; use super::img::Img; -use super::renderer::Renderer; -use super::store::Store; pub struct Sprite { ///A sprite with animations (using the function animate) - pos: (u8, u8), + pos: (u32, u32), frames: Vec, anims: Vec<(usize, usize)>, current_anim: usize, @@ -20,7 +16,7 @@ pub struct Sprite { /// Wrapper for the Img struct that handles animations and location. impl Sprite { - pub fn new(pos: (u8, u8), frames: Vec, anims: Vec<(usize, usize)>, framerate: f64) -> Self { + pub fn new(pos: (u32, u32), frames: Vec, anims: Vec<(usize, usize)>, framerate: f64) -> Self { Self { pos, frames, @@ -46,16 +42,16 @@ impl Sprite { } } - pub fn get_pos(&self) -> (u8, u8) { return self.pos.clone(); } + pub fn get_pos(&self) -> (u32, u32) { return self.pos.clone() } - pub fn set_pos(&mut self, pos: (u8, u8)) { self.pos = pos } + pub fn set_pos(&mut self, pos: (u32, u32)) { self.pos = pos } - pub fn get_width(&self) -> i32 { - return self.get_current_frame().get_width().clone() as i32; + pub fn get_width(&self) -> u32 { + return self.get_current_frame().get_width().clone() as u32; } - pub fn get_height(&self) -> i32 { - return self.get_current_frame().get_pixels().len() as i32 / *self.get_current_frame().get_width() as i32; + pub fn get_height(&self) -> u32 { + return 2 * (self.get_current_frame().get_length() / *self.get_current_frame().get_width()) as u32; } pub fn get_current_frame(&self) -> Img { @@ -63,14 +59,17 @@ impl Sprite { } /// Wraps Img::new_from_file. - pub fn new_from_File(mut f: File, pix_per_frame: usize, pos: (u8, u8), anims: Vec<(usize, usize)>, framerate: f64) -> Self { + pub fn new_from_file(mut f: File, pix_per_frame: usize, pos: (u32, u32), anims: Vec<(usize, usize)>, framerate: f64) -> Self { let mut width = 0; let mut pixels = vec![]; let mut frames = vec![]; let real_pix_per_frame = pix_per_frame / 2; let mut buf: Vec = vec![]; - f.read_to_end(&mut buf); + match f.read_to_end(&mut buf) { + Ok(_) => {}, + Err(e) => eprintln!("Could not read image buffer: {}", e), + } if buf.len() < 4 { return Self { @@ -86,7 +85,7 @@ impl Sprite { let mut ctr = 0; - for (num) in buf.iter() { + for num in buf.iter() { if ctr >= 4 { if (ctr - 4) % real_pix_per_frame == 0 { pixels = vec![*num]; @@ -112,6 +111,6 @@ impl Sprite { current_frame: 0, dt_since_last_frame: 0.0, framerate, - }; + } } } diff --git a/src/store.rs b/src/store.rs index 0f78cee..8bd4d85 100644 --- a/src/store.rs +++ b/src/store.rs @@ -1,6 +1,5 @@ use super::action::Action; use super::action::MenuSubAction; -use super::dispatcher::Dispatcher; pub enum ReceiveActionReturnOption<'a> { NoNewAction(&'a mut Store<'a>), diff --git a/src/test_obj.rs b/src/test_object.rs similarity index 83% rename from src/test_obj.rs rename to src/test_object.rs index 1863fa8..9bf26d1 100644 --- a/src/test_obj.rs +++ b/src/test_object.rs @@ -1,16 +1,14 @@ -use action::{Action, MenuSubAction}; -use dispatcher::Dispatcher; -use img::Img; +use action::Action; use sprite::Sprite; use store::ReceiveActionReturnOption; use store::Store; -pub struct TestObj { +pub struct TestObject { ///A game object for testing sprite: Option, } -impl<'a> TestObj { +impl<'a> TestObject { pub fn new(sprite: Sprite) -> Self { Self { sprite: Some(sprite), @@ -36,10 +34,10 @@ impl<'a> TestObj { } } -impl<'a> Store<'a> for TestObj { +impl<'a> Store<'a> for TestObject { fn receive_action(&'a mut self, action: &Action, dt: &f64) -> ReceiveActionReturnOption<'a> { match action { - &Action::SendFrameAction => { + &Action::SendFrameAction(w, h, p) => { return ReceiveActionReturnOption::NewAction( vec!( self.send_frame(dt.clone()) @@ -51,4 +49,4 @@ impl<'a> Store<'a> for TestObj { _ => return ReceiveActionReturnOption::NoNewAction(self) } } -} +} \ No newline at end of file diff --git a/src/tests.rs b/src/tests.rs index 217c010..319613e 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -14,7 +14,7 @@ use action::MenuSubAction; use button::Button; use scene_manager::MinimalScene; use scene_manager::SceneManager; -use test_obj::TestObj; +use test_object::TestObj; use super::action::Action; use super::dispatcher::Dispatcher; @@ -86,7 +86,7 @@ fn test_renderer() { match File::open("./resources/test_img.u4i") { Ok(f) => { - test_img = Img::new_from_File(f); + test_img = Img::new_from_file(f); } Err(e) => { print!("{}", e); @@ -104,7 +104,7 @@ fn test_sprites_and_menus() { match File::open("./resources/test_sprite.u4i") { Ok(f) => { - test_sprite = Sprite::new_from_File( + test_sprite = Sprite::new_from_file( f, 16, (0, 0), @@ -121,7 +121,7 @@ fn test_sprites_and_menus() { match File::open("./resources/exit_button.u4i") { Ok(f) => { - button_sprite = Sprite::new_from_File( + button_sprite = Sprite::new_from_file( f, 133, (0, 0),