diff --git a/game/src/scenes/fsm_error_screen.rs b/game/src/scenes/fsm_error_screen.rs index 7a57148..b6d1709 100644 --- a/game/src/scenes/fsm_error_screen.rs +++ b/game/src/scenes/fsm_error_screen.rs @@ -48,7 +48,7 @@ impl Action for FsmErrorScreen { } impl ScreenSpaceRender for FsmErrorScreen { - fn render_screen_space(&self, raylib: &mut HackedRaylibHandle, config: &GameConfig) { + fn render_screen_space(&mut self, raylib: &mut HackedRaylibHandle, config: &GameConfig) { raylib.clear_background(Color::RED); // Render a warning message diff --git a/game/src/scenes/how_to_play_screen.rs b/game/src/scenes/how_to_play_screen.rs new file mode 100644 index 0000000..1537345 --- /dev/null +++ b/game/src/scenes/how_to_play_screen.rs @@ -0,0 +1,170 @@ +use std::ops::{Div, Sub}; + +use chrono::{DateTime, Utc}; +use dirty_fsm::{Action, ActionFlag}; +use pkg_version::pkg_version_major; +use raylib::prelude::*; + +use crate::{GameConfig, context::GameContext, utilities::{ + datastore::{load_texture_from_internal_data, ResourceLoadError}, + game_version::get_version_string, + math::interpolate_exp, + non_ref_raylib::HackedRaylibHandle, + render_layer::ScreenSpaceRender, + }}; + +use super::{Scenes, ScreenError}; +use tracing::{debug, info, trace}; + +#[derive(Debug)] +pub struct HowToPlayScreen { + is_btm_pressed: bool //Is back to menu button pressed +} + +impl HowToPlayScreen { + /// Construct a new `HowToPlayScreen` + pub fn new() -> Self { + Self { + is_btm_pressed: false + } + } +} + +impl Action for HowToPlayScreen { + fn on_register(&mut self) -> Result<(), ScreenError> { + debug!("Registered"); + Ok(()) + } + + fn on_first_run(&mut self, _context: &GameContext) -> Result<(), ScreenError> { + debug!("Running HowToPlayScreen for the first time"); + + Ok(()) + } + + fn execute( + &mut self, + _delta: &chrono::Duration, + context: &GameContext, + ) -> Result, ScreenError> { + trace!("execute() called on HowToPlayScreen"); + self.render_screen_space(&mut context.renderer.borrow_mut(), &context.config); + + if self.is_btm_pressed { + Ok(ActionFlag::SwitchState(Scenes::MainMenuScreen)) + } + else{ + Ok(ActionFlag::Continue) + } + } + + fn on_finish(&mut self, _interrupted: bool) -> Result<(), ScreenError> { + debug!("Finished HowToPlayScreen"); + self.is_btm_pressed = false; + Ok(()) + } +} + +impl ScreenSpaceRender for HowToPlayScreen { + fn render_screen_space( + &mut self, + raylib: &mut crate::utilities::non_ref_raylib::HackedRaylibHandle, + config: &GameConfig + ) { + + // Render the background + raylib.clear_background(Color::BLACK); + + let screen_size = raylib.get_screen_size(); + + //Mouse Position + let mouse_position: Vector2 = raylib.get_mouse_position(); + + let mouse_pressed: bool = raylib.is_mouse_button_pressed(MouseButton::MOUSE_LEFT_BUTTON); + + raylib.draw_text( + + "How to Play", + 37, + 80, + 70, + Color::BLUE, + ); + + raylib.draw_text( + + "How to Play", + 43, + 80, + 70, + Color::RED, + ); + + raylib.draw_text( + + "How to Play", + 40, + 80, + 70, + Color::WHITE, + ); + + //Back to Menu + if Rectangle::new(35.0, screen_size.y as f32 - 80.0, 200.0, 40.0).check_collision_point_rec(mouse_position){ + raylib.draw_text( + + "BACK TO MENU", + 28, + screen_size.y as i32 - 50, + 25, + Color::RED, + ); + raylib.draw_text( + + "BACK TO MENU", + 22, + screen_size.y as i32 - 50, + 25, + Color::BLUE, + ); + raylib.draw_text( + + "BACK TO MENU", + 25, + screen_size.y as i32 - 50, + 25, + Color::WHITE, + ); + + if mouse_pressed{ + self.is_btm_pressed = true; + } + } + else { + raylib.draw_text( + + "BACK TO MENU", + 26, + screen_size.y as i32 - 50, + 25, + Color::RED, + ); + raylib.draw_text( + + "BACK TO MENU", + 24, + screen_size.y as i32 - 50, + 25, + Color::BLUE, + ); + raylib.draw_text( + + "BACK TO MENU", + 25, + screen_size.y as i32 - 50, + 25, + Color::WHITE, + ); + } + } +} diff --git a/game/src/scenes/ingame_scene/hud.rs b/game/src/scenes/ingame_scene/hud.rs index 44d3b3f..bdcd6bd 100644 --- a/game/src/scenes/ingame_scene/hud.rs +++ b/game/src/scenes/ingame_scene/hud.rs @@ -4,7 +4,7 @@ use super::InGameScreen; impl ScreenSpaceRender for InGameScreen { fn render_screen_space( - &self, + &mut self, raylib: &mut crate::utilities::non_ref_raylib::HackedRaylibHandle, config: &GameConfig ) { diff --git a/game/src/scenes/ingame_scene/world.rs b/game/src/scenes/ingame_scene/world.rs index 67e4ab5..75c6491 100644 --- a/game/src/scenes/ingame_scene/world.rs +++ b/game/src/scenes/ingame_scene/world.rs @@ -10,7 +10,7 @@ use raylib::prelude::*; impl WorldSpaceRender for InGameScreen { fn render_world_space( - &self, + &mut self, raylib: &mut RaylibMode2D<'_, HackedRaylibHandle>, config: &GameConfig, ) { diff --git a/game/src/scenes/loading_screen.rs b/game/src/scenes/loading_screen.rs index 0ccc70b..d5b56cc 100644 --- a/game/src/scenes/loading_screen.rs +++ b/game/src/scenes/loading_screen.rs @@ -102,7 +102,7 @@ impl Action for LoadingScreen { impl ScreenSpaceRender for LoadingScreen { fn render_screen_space( - &self, + &mut self, raylib: &mut crate::utilities::non_ref_raylib::HackedRaylibHandle, config: &GameConfig ) { diff --git a/game/src/scenes/main_menu_screen.rs b/game/src/scenes/main_menu_screen.rs index cc0f68b..4c5168d 100644 --- a/game/src/scenes/main_menu_screen.rs +++ b/game/src/scenes/main_menu_screen.rs @@ -17,12 +17,22 @@ use super::{Scenes, ScreenError}; use tracing::{debug, info, trace}; #[derive(Debug)] -pub struct MainMenuScreen {} +pub struct MainMenuScreen { + + is_start_pressed: bool, //Is start button pressed + is_htp_pressed: bool, //Is how to play button pressed + is_options_pressed: bool //Is options button pressed + +} impl MainMenuScreen { /// Construct a new `MainMenuScreen` pub fn new() -> Self { - Self {} + Self { + is_start_pressed: false, + is_htp_pressed: false, + is_options_pressed: false + } } } @@ -46,23 +56,32 @@ impl Action for MainMenuScreen { trace!("execute() called on MainMenuScreen"); self.render_screen_space(&mut context.renderer.borrow_mut(), &context.config); - // TODO: TEMP - if context.renderer.borrow_mut().is_key_pressed(KeyboardKey::KEY_SPACE) { + if self.is_start_pressed { Ok(ActionFlag::SwitchState(Scenes::InGameScene)) - } else { + } + else if self.is_htp_pressed { + Ok(ActionFlag::SwitchState(Scenes::HowToPlayScreen)) + } + else if self.is_options_pressed { + Ok(ActionFlag::SwitchState(Scenes::OptionsScreen)) + } + else { Ok(ActionFlag::Continue) } } fn on_finish(&mut self, _interrupted: bool) -> Result<(), ScreenError> { debug!("Finished MainMenuScreen"); + self.is_start_pressed = false; + self.is_htp_pressed = false; + self.is_options_pressed = false; Ok(()) } } impl ScreenSpaceRender for MainMenuScreen { fn render_screen_space( - &self, + &mut self, raylib: &mut crate::utilities::non_ref_raylib::HackedRaylibHandle, config: &GameConfig ) { @@ -72,6 +91,11 @@ impl ScreenSpaceRender for MainMenuScreen { // Calculate the logo position let screen_size = raylib.get_screen_size(); + //Mouse Position + let mouse_position: Vector2 = raylib.get_mouse_position(); + + let mouse_pressed: bool = raylib.is_mouse_button_pressed(MouseButton::MOUSE_LEFT_BUTTON); + // Only in debug mode, render a debug message #[cfg(debug_assertions)] { @@ -83,6 +107,16 @@ impl ScreenSpaceRender for MainMenuScreen { Color::WHITE, ); } + + // Displays mouse position + raylib.draw_text( + &format!("[{}, {}]", mouse_position.x, mouse_position.y), + screen_size.x as i32 - 130, + screen_size.y as i32 - 30, + 25, + Color::DARKGRAY, + ); + // Render the game version info raylib.draw_text( &format!( @@ -95,5 +129,207 @@ impl ScreenSpaceRender for MainMenuScreen { 15, Color::WHITE, ); + + raylib.draw_text( + + &format!("[{}]", config.name), + 37, + 80, + 70, + Color::BLUE, + ); + + raylib.draw_text( + + &format!("[{}]", config.name), + 43, + 80, + 70, + Color::RED, + ); + + raylib.draw_text( + + &format!("[{}]", config.name), + 40, + 80, + 70, + Color::WHITE, + ); + + // Start Game + if Rectangle::new(80.0, 300.0, 170.0, 20.0).check_collision_point_rec(mouse_position) { + raylib.draw_text( + + "START GAME", + 83, + 300, + 25, + Color::RED, + ); + raylib.draw_text( + + "START GAME", + 77, + 300, + 25, + Color::BLUE, + ); + raylib.draw_text( + + "START GAME", + 80, + 300, + 25, + Color::WHITE, + ); + + if mouse_pressed{ + self.is_start_pressed = true; + } + } + else{ + raylib.draw_text( + + "START GAME", + 81, + 300, + 25, + Color::RED, + ); + raylib.draw_text( + + "START GAME", + 79, + 300, + 25, + Color::BLUE, + ); + raylib.draw_text( + + "START GAME", + 80, + 300, + 25, + Color::WHITE, + ); + } + + // How to Play + if Rectangle::new(80.0, 350.0, 170.0, 20.0).check_collision_point_rec(mouse_position) { + raylib.draw_text( + + "HOW TO PLAY", + 83, + 350, + 25, + Color::RED, + ); + raylib.draw_text( + + "HOW TO PLAY", + 77, + 350, + 25, + Color::BLUE, + ); + raylib.draw_text( + + "HOW TO PLAY", + 80, + 350, + 25, + Color::WHITE, + ); + + if mouse_pressed{ + self.is_htp_pressed = true; + } + } + else{ + raylib.draw_text( + + "HOW TO PLAY", + 81, + 350, + 25, + Color::RED, + ); + raylib.draw_text( + + "HOW TO PLAY", + 79, + 350, + 25, + Color::BLUE, + ); + raylib.draw_text( + + "HOW TO PLAY", + 80, + 350, + 25, + Color::WHITE, + ); + } + + // OPTIONS + if Rectangle::new(80.0, 400.0, 135.0, 20.0).check_collision_point_rec(mouse_position) { + raylib.draw_text( + + "OPTIONS", + 83, + 400, + 25, + Color::RED, + ); + raylib.draw_text( + + "OPTIONS", + 77, + 400, + 25, + Color::BLUE, + ); + raylib.draw_text( + + "OPTIONS", + 80, + 400, + 25, + Color::WHITE, + ); + + if mouse_pressed{ + self.is_options_pressed = true; + } + + } + else{ + raylib.draw_text( + + "OPTIONS", + 81, + 400, + 25, + Color::RED, + ); + raylib.draw_text( + + "OPTIONS", + 79, + 400, + 25, + Color::BLUE, + ); + raylib.draw_text( + + "OPTIONS", + 80, + 400, + 25, + Color::WHITE, + ); + } } } diff --git a/game/src/scenes/mod.rs b/game/src/scenes/mod.rs index d9ec17b..b43e426 100644 --- a/game/src/scenes/mod.rs +++ b/game/src/scenes/mod.rs @@ -1,7 +1,4 @@ -use self::{ - fsm_error_screen::FsmErrorScreen, ingame_scene::InGameScreen, loading_screen::LoadingScreen, - main_menu_screen::MainMenuScreen, -}; +use self::{fsm_error_screen::FsmErrorScreen, options_screen::OptionsScreen, how_to_play_screen::HowToPlayScreen, ingame_scene::InGameScreen, loading_screen::LoadingScreen, main_menu_screen::MainMenuScreen}; use crate::{ context::GameContext, utilities::{ @@ -16,6 +13,8 @@ pub mod fsm_error_screen; pub mod ingame_scene; pub mod loading_screen; pub mod main_menu_screen; +pub mod how_to_play_screen; +pub mod options_screen; /// Defines all scenes #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash)] @@ -25,6 +24,8 @@ pub enum Scenes { LoadingScreen, MainMenuScreen, InGameScene, + HowToPlayScreen, + OptionsScreen, } /// Contains any possible errors thrown while rendering @@ -56,5 +57,8 @@ pub fn build_screen_state_machine( )?; machine.add_action(Scenes::MainMenuScreen, MainMenuScreen::new())?; machine.add_action(Scenes::InGameScene, InGameScreen::new(player_sprite_sheet))?; + machine.add_action(Scenes::HowToPlayScreen, HowToPlayScreen::new())?; + machine.add_action(Scenes::OptionsScreen, OptionsScreen::new())?; Ok(machine) + } diff --git a/game/src/scenes/options_screen.rs b/game/src/scenes/options_screen.rs new file mode 100644 index 0000000..bf51602 --- /dev/null +++ b/game/src/scenes/options_screen.rs @@ -0,0 +1,171 @@ +use std::ops::{Div, Sub}; + +use chrono::{DateTime, Utc}; +use dirty_fsm::{Action, ActionFlag}; +use pkg_version::pkg_version_major; +use raylib::prelude::*; + +use crate::{GameConfig, context::GameContext, utilities::{ + datastore::{load_texture_from_internal_data, ResourceLoadError}, + game_version::get_version_string, + math::interpolate_exp, + non_ref_raylib::HackedRaylibHandle, + render_layer::ScreenSpaceRender, + }}; + +use super::{Scenes, ScreenError}; +use tracing::{debug, info, trace}; + +#[derive(Debug)] +pub struct OptionsScreen { + is_btm_pressed: bool //Is back to menu button pressed +} + +impl OptionsScreen { + /// Construct a new `OptionsScreen` + pub fn new() -> Self { + Self { + is_btm_pressed: false + } + } +} + +impl Action for OptionsScreen { + fn on_register(&mut self) -> Result<(), ScreenError> { + debug!("Registered"); + Ok(()) + } + + fn on_first_run(&mut self, _context: &GameContext) -> Result<(), ScreenError> { + debug!("Running OptionsScreen for the first time"); + + Ok(()) + } + + fn execute( + &mut self, + _delta: &chrono::Duration, + context: &GameContext, + ) -> Result, ScreenError> { + trace!("execute() called on OptionsScreen"); + self.render_screen_space(&mut context.renderer.borrow_mut(), &context.config); + + if self.is_btm_pressed { + Ok(ActionFlag::SwitchState(Scenes::MainMenuScreen)) + } + else{ + Ok(ActionFlag::Continue) + } + } + + fn on_finish(&mut self, _interrupted: bool) -> Result<(), ScreenError> { + debug!("Finished OptionsScreen"); + self.is_btm_pressed = false; + Ok(()) + } +} + +impl ScreenSpaceRender for OptionsScreen { + fn render_screen_space( + &mut self, + raylib: &mut crate::utilities::non_ref_raylib::HackedRaylibHandle, + config: &GameConfig + ) { + + // Render the background + raylib.clear_background(Color::BLACK); + + let screen_size = raylib.get_screen_size(); + + //Mouse Position + let mouse_position: Vector2 = raylib.get_mouse_position(); + + let mouse_pressed: bool = raylib.is_mouse_button_pressed(MouseButton::MOUSE_LEFT_BUTTON); + + raylib.draw_text( + + "Options", + 37, + 80, + 70, + Color::BLUE, + ); + + raylib.draw_text( + + "Options", + 43, + 80, + 70, + Color::RED, + ); + + raylib.draw_text( + + "Options", + 40, + 80, + 70, + Color::WHITE, + ); + + //Back to Menu + if Rectangle::new(35.0, screen_size.y as f32 - 80.0, 200.0, 40.0).check_collision_point_rec(mouse_position){ + raylib.draw_text( + + "BACK TO MENU", + 28, + screen_size.y as i32 - 50, + 25, + Color::RED, + ); + raylib.draw_text( + + "BACK TO MENU", + 22, + screen_size.y as i32 - 50, + 25, + Color::BLUE, + ); + raylib.draw_text( + + "BACK TO MENU", + 25, + screen_size.y as i32 - 50, + 25, + Color::WHITE, + ); + + if mouse_pressed{ + self.is_btm_pressed = true; + + } + } + else { + raylib.draw_text( + + "BACK TO MENU", + 26, + screen_size.y as i32 - 50, + 25, + Color::RED, + ); + raylib.draw_text( + + "BACK TO MENU", + 24, + screen_size.y as i32 - 50, + 25, + Color::BLUE, + ); + raylib.draw_text( + + "BACK TO MENU", + 25, + screen_size.y as i32 - 50, + 25, + Color::WHITE, + ); + } + } +} diff --git a/game/src/utilities/render_layer.rs b/game/src/utilities/render_layer.rs index 8b5710e..9de55ab 100644 --- a/game/src/utilities/render_layer.rs +++ b/game/src/utilities/render_layer.rs @@ -7,9 +7,9 @@ pub trait FrameUpdate { } pub trait ScreenSpaceRender { - fn render_screen_space(&self, raylib: &mut HackedRaylibHandle, config: &GameConfig); + fn render_screen_space(&mut self, raylib: &mut HackedRaylibHandle, config: &GameConfig); } pub trait WorldSpaceRender { - fn render_world_space(&self, raylib: &mut RaylibMode2D<'_, HackedRaylibHandle>, config: &GameConfig); + fn render_world_space(&mut self, raylib: &mut RaylibMode2D<'_, HackedRaylibHandle>, config: &GameConfig); }