diff --git a/game/assets/background.png b/game/assets/background.png new file mode 100644 index 0000000..1e6e438 Binary files /dev/null and b/game/assets/background.png differ diff --git a/game/assets/levels/level_0/background.png b/game/assets/levels/level_0/background.png index 1e6e438..140b63e 100644 Binary files a/game/assets/levels/level_0/background.png and b/game/assets/levels/level_0/background.png differ diff --git a/game/src/character/mod.rs b/game/src/character/mod.rs index 872d7fb..c32b7f0 100644 --- a/game/src/character/mod.rs +++ b/game/src/character/mod.rs @@ -21,6 +21,7 @@ pub enum CharacterState { #[derive(Debug)] pub struct MainCharacter { + pub start_position: Vector2, pub position: Vector2, pub movement_force: Vector2, pub base_velocity: Vector2, @@ -34,6 +35,7 @@ pub struct MainCharacter { impl MainCharacter { pub fn new(position: Vector2, sprite_sheet: Texture2D) -> Self { Self { + start_position: position.clone(), position, movement_force: Vector2::zero(), velocity: Vector2::zero(), @@ -78,7 +80,7 @@ impl MainCharacter { } pub fn reset(&mut self) { - self.position = Vector2::new(0.0, 0.0); + self.position = self.start_position; self.velocity = Vector2::zero(); self.movement_force = Vector2::zero(); self.current_state = CharacterState::default(); diff --git a/game/src/context.rs b/game/src/context.rs index a3e0ac3..a37ebde 100644 --- a/game/src/context.rs +++ b/game/src/context.rs @@ -5,11 +5,17 @@ use discord_sdk::activity::ActivityBuilder; use crate::{GameConfig, utilities::non_ref_raylib::HackedRaylibHandle}; +#[derive(Debug)] +pub enum ControlFlag { + Quit +} + #[derive(Debug)] pub struct GameContext { pub renderer: RefCell, pub config: GameConfig, - pub discord_rpc_send: Sender> + pub discord_rpc_send: Sender>, + pub flag_send: Sender> } // impl GameContext { diff --git a/game/src/lib.rs b/game/src/lib.rs index d6a98ca..7b053c4 100644 --- a/game/src/lib.rs +++ b/game/src/lib.rs @@ -144,6 +144,9 @@ pub async fn game_begin(game_config: &mut GameConfig) -> Result<(), Box Result<(), Box Result<(), Box Result<(), Box { + if let Some(flag) = flag { + match flag { + context::ControlFlag::Quit => break, + } + } + } + Err(TryRecvError::Empty) => {} + Err(TryRecvError::Disconnected) => { + break; + } + } } Ok(()) } diff --git a/game/src/scenes/how_to_play_screen.rs b/game/src/scenes/how_to_play_screen.rs index 1537345..e69ba4b 100644 --- a/game/src/scenes/how_to_play_screen.rs +++ b/game/src/scenes/how_to_play_screen.rs @@ -5,27 +5,31 @@ use dirty_fsm::{Action, ActionFlag}; use pkg_version::pkg_version_major; use raylib::prelude::*; -use crate::{GameConfig, context::GameContext, utilities::{ +use crate::{ + 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, - }}; + }, + GameConfig, +}; use super::{Scenes, ScreenError}; use tracing::{debug, info, trace}; #[derive(Debug)] pub struct HowToPlayScreen { - is_btm_pressed: bool //Is back to menu button pressed + 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 + is_btm_pressed: false, } } } @@ -52,8 +56,7 @@ impl Action for HowToPlayScreen { if self.is_btm_pressed { Ok(ActionFlag::SwitchState(Scenes::MainMenuScreen)) - } - else{ + } else { Ok(ActionFlag::Continue) } } @@ -69,11 +72,19 @@ impl ScreenSpaceRender for HowToPlayScreen { fn render_screen_space( &mut self, raylib: &mut crate::utilities::non_ref_raylib::HackedRaylibHandle, - config: &GameConfig + config: &GameConfig, ) { + let screen_size = raylib.get_screen_size(); // Render the background raylib.clear_background(Color::BLACK); + raylib.draw_rectangle_lines( + 0, + 0, + screen_size.x as i32, + screen_size.y as i32, + config.colors.white, + ); let screen_size = raylib.get_screen_size(); @@ -82,89 +93,34 @@ impl ScreenSpaceRender for HowToPlayScreen { let mouse_pressed: bool = raylib.is_mouse_button_pressed(MouseButton::MOUSE_LEFT_BUTTON); - raylib.draw_text( - + //Render the title + raylib.draw_rgb_split_text( + Vector2::new(40.0, 80.0), "How to Play", - 37, - 80, 70, - Color::BLUE, + true, + Color::WHITE, ); - raylib.draw_text( - - "How to Play", - 43, - 80, - 70, - Color::RED, - ); - - raylib.draw_text( - - "How to Play", - 40, - 80, - 70, + // Render the instructions + raylib.draw_rgb_split_text( + Vector2::new(100.0, 300.0), + ">> SPACE to jump\n>> SHIFT to dash\n>> Don't die", + 45, + true, 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, - ); - } + let hovering_back_button = Rectangle::new(35.0, screen_size.y as f32 - 80.0, 200.0, 40.0) + .check_collision_point_rec(mouse_position); + raylib.draw_rgb_split_text( + Vector2::new(25.0, screen_size.y - 50.0), + "BACK TO MENU", + 25, + hovering_back_button, + Color::WHITE, + ); + self.is_btm_pressed = hovering_back_button && mouse_pressed; } } diff --git a/game/src/scenes/ingame_scene/mod.rs b/game/src/scenes/ingame_scene/mod.rs index af5e290..0c79482 100644 --- a/game/src/scenes/ingame_scene/mod.rs +++ b/game/src/scenes/ingame_scene/mod.rs @@ -117,7 +117,8 @@ impl Action for InGameScreen { } else if self.player_dead { // TODO: (luna) make this switch to the death screen plz - Ok(ActionFlag::SwitchState(Scenes::FsmErrorScreen)) + // Ok(ActionFlag::SwitchState(Scenes::FsmErrorScreen)) + Ok(ActionFlag::Continue) } else { Ok(ActionFlag::Continue) } diff --git a/game/src/scenes/loading_screen.rs b/game/src/scenes/loading_screen.rs deleted file mode 100644 index 62d6e7c..0000000 --- a/game/src/scenes/loading_screen.rs +++ /dev/null @@ -1,164 +0,0 @@ -use std::ops::{Div, Sub}; - -use cfg_if::cfg_if; -use chrono::{DateTime, Utc}; -use dirty_fsm::{Action, ActionFlag}; -use discord_sdk::activity::{ActivityBuilder, Assets}; -use raylib::prelude::*; - -use crate::{GameConfig, context::GameContext, utilities::{ - datastore::{load_texture_from_internal_data, ResourceLoadError}, - math::interpolate_exp, - non_ref_raylib::HackedRaylibHandle, - render_layer::ScreenSpaceRender, - }}; - -use super::{Scenes, ScreenError}; -use tracing::{debug, info, error, trace}; - -/// Defines how long the loading screen should be displayed. -const LOADING_SCREEN_DURATION_SECONDS: u8 = 3; - -#[derive(Debug)] -pub struct LoadingScreen { - start_timestamp: Option>, - game_logo_texture: Texture2D, - game_logo_size: Vector2, -} - -impl LoadingScreen { - /// Construct a new `LoadingScreen` - pub fn new( - raylib_handle: &mut HackedRaylibHandle, - thread: &RaylibThread, - ) -> Result { - // Load the game logo asset - let game_logo = - load_texture_from_internal_data(raylib_handle, thread, "logos/game-logo.png")?; - - Ok(Self { - start_timestamp: None, - game_logo_size: Vector2::new(game_logo.width as f32, game_logo.height as f32), - game_logo_texture: game_logo, - }) - } -} - -impl Action for LoadingScreen { - fn on_register(&mut self) -> Result<(), ScreenError> { - debug!("Registered"); - Ok(()) - } - - fn on_first_run(&mut self, context: &GameContext) -> Result<(), ScreenError> { - debug!("Running LoadingScreen for the first time"); - - // Update discord - if let Err(e) = context.discord_rpc_send.send(Some( - ActivityBuilder::default().details("loading...").assets( - Assets::default().large("game-logo-small", Some(context.config.name.clone())), - ), - )) { - error!("Failed to update discord: {}", e); - } - - // Keep track of when this screen is opened - self.start_timestamp = Some(Utc::now()); - - Ok(()) - } - - fn execute( - &mut self, - _delta: &chrono::Duration, - context: &GameContext, - ) -> Result, ScreenError> { - trace!("execute() called on LoadingScreen"); - self.render_screen_space(&mut context.renderer.borrow_mut(), &context.config); - - // Check for a quick skip button in debug builds - cfg_if! { - if #[cfg(debug_assertions)] { - let debug_skip_screen = context.renderer.borrow_mut().is_key_pressed(KeyboardKey::KEY_ESCAPE); - } else { - let debug_skip_screen = false; - } - } - - // Keep rendering until we pass the loading screen duration - if let Some(start_timestamp) = self.start_timestamp { - let duration = Utc::now().signed_duration_since(start_timestamp); - if duration.num_seconds() >= LOADING_SCREEN_DURATION_SECONDS as i64 || debug_skip_screen - { - info!("LoadingScreen duration reached, moving to next screen"); - Ok(ActionFlag::SwitchState(Scenes::MainMenuScreen)) - } else { - Ok(ActionFlag::Continue) - } - } else { - Ok(ActionFlag::Continue) - } - } - - fn on_finish(&mut self, _interrupted: bool) -> Result<(), ScreenError> { - debug!("Finished LoadingScreen"); - - // Reset the start timestamp - self.start_timestamp = None; - - Ok(()) - } -} - -impl ScreenSpaceRender for LoadingScreen { - fn render_screen_space( - &mut self, - raylib: &mut crate::utilities::non_ref_raylib::HackedRaylibHandle, - config: &GameConfig - ) { - // Calculate the loading screen fade in/out value - // This makes the loading screen fade in/out over the duration of the loading screen - let cur_time = Utc::now(); - let time_since_start = - cur_time.signed_duration_since(self.start_timestamp.unwrap_or(cur_time)); - let fade_percentage = interpolate_exp( - time_since_start.num_milliseconds() as f32, - 0.0..(LOADING_SCREEN_DURATION_SECONDS as f32 * 1000.0), - 0.0..1.0, - 8.0, - ); - trace!("Loading screen fade at {:.2}%", fade_percentage); - - // Render the background - raylib.clear_background(Color::BLACK); - - // Calculate the logo position - let screen_size = raylib.get_screen_size(); - - // Render the game logo - raylib.draw_texture_ex( - &self.game_logo_texture, - screen_size.div(2.0).sub(self.game_logo_size.div(2.0)), - 0.0, - 1.0, - Color::WHITE.fade(fade_percentage), - ); - - // Only in debug mode, render a debug message - #[cfg(debug_assertions)] - { - raylib.draw_rectangle_v( - Vector2::zero(), - Vector2::new(screen_size.x, 40.0), - Color::RED, - ); - raylib.draw_text( - "Game in DEBUG MODE. Do not redistribute!", - 10, - 10, - 20, - Color::WHITE, - ); - } - } -} diff --git a/game/src/scenes/main_menu_screen.rs b/game/src/scenes/main_menu_screen.rs index 1ee95a6..8910661 100644 --- a/game/src/scenes/main_menu_screen.rs +++ b/game/src/scenes/main_menu_screen.rs @@ -6,29 +6,23 @@ use discord_sdk::activity::{ActivityBuilder, Assets}; use pkg_version::pkg_version_major; use raylib::prelude::*; -use crate::{ - context::GameContext, - utilities::{ +use crate::{GameConfig, context::{ControlFlag, GameContext}, utilities::{ datastore::{load_texture_from_internal_data, ResourceLoadError}, game_version::get_version_string, math::interpolate_exp, non_ref_raylib::HackedRaylibHandle, render_layer::ScreenSpaceRender, - }, - GameConfig, -}; + }}; use super::{Scenes, ScreenError}; use tracing::{debug, error, info, trace}; #[derive(Debug)] pub struct MainMenuScreen { - - is_start_pressed: bool, //Is start button pressed - is_htp_pressed: bool, //Is how to play button pressed + 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 - is_quit_pressed: bool //Is quit button pressed - + is_quit_pressed: bool, //Is quit button pressed } impl MainMenuScreen { @@ -38,7 +32,7 @@ impl MainMenuScreen { is_start_pressed: false, is_htp_pressed: false, is_options_pressed: false, - is_quit_pressed: false + is_quit_pressed: false, } } } @@ -74,17 +68,14 @@ impl Action for MainMenuScreen { if self.is_start_pressed { Ok(ActionFlag::SwitchState(Scenes::InGameScene)) - } - else if self.is_htp_pressed { + } else if self.is_htp_pressed { Ok(ActionFlag::SwitchState(Scenes::HowToPlayScreen)) - } - else if self.is_options_pressed { + } else if self.is_options_pressed { Ok(ActionFlag::SwitchState(Scenes::OptionsScreen)) - } - else if self.is_quit_pressed { - panic!(); - } - else { + } else if self.is_quit_pressed { + context.flag_send.send(Some(ControlFlag::Quit)).unwrap(); + Ok(ActionFlag::Continue) + } else { Ok(ActionFlag::Continue) } } @@ -105,8 +96,17 @@ impl ScreenSpaceRender for MainMenuScreen { raylib: &mut crate::utilities::non_ref_raylib::HackedRaylibHandle, config: &GameConfig, ) { + let screen_size = raylib.get_screen_size(); + // Render the background raylib.clear_background(Color::BLACK); + raylib.draw_rectangle_lines( + 0, + 0, + screen_size.x as i32, + screen_size.y as i32, + config.colors.white, + ); // Calculate the logo position let screen_size = raylib.get_screen_size(); @@ -150,269 +150,61 @@ impl ScreenSpaceRender for MainMenuScreen { Color::WHITE, ); - raylib.draw_text( - + // Render the title + raylib.draw_rgb_split_text( + Vector2::new(37.0, 80.0), &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, + true, 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, - ); - } + let hovering_start_game = + Rectangle::new(80.0, 300.0, 170.0, 20.0).check_collision_point_rec(mouse_position); + raylib.draw_rgb_split_text( + Vector2::new(80.0, 300.0), + "START GAME", + 25, + hovering_start_game, + Color::WHITE, + ); + self.is_start_pressed = mouse_pressed && hovering_start_game; // 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, - ); - } + let hovering_htp = + Rectangle::new(80.0, 350.0, 170.0, 20.0).check_collision_point_rec(mouse_position); + raylib.draw_rgb_split_text( + Vector2::new(80.0, 350.0), + "HOW TO PLAY", + 25, + hovering_htp, + Color::WHITE, + ); + self.is_htp_pressed = mouse_pressed && hovering_htp; // 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, - ); - - - } + let hovering_options = + Rectangle::new(80.0, 400.0, 135.0, 20.0).check_collision_point_rec(mouse_position); + raylib.draw_rgb_split_text( + Vector2::new(80.0, 400.0), + "OPTIONS", + 25, + hovering_options, + Color::WHITE, + ); + self.is_options_pressed = mouse_pressed && hovering_options; // QUIT - if Rectangle::new(80.0, 445.0, 65.0, 20.0).check_collision_point_rec(mouse_position) { - raylib.draw_text( - - "QUIT", - 83, - 450, - 25, - Color::RED, - ); - raylib.draw_text( - - "QUIT", - 77, - 450, - 25, - Color::BLUE, - ); - raylib.draw_text( - - "QUIT", - 80, - 450, - 25, - Color::WHITE, - ); - - if mouse_pressed{ - self.is_quit_pressed = true; - } - - } - else{ - raylib.draw_text( - - "QUIT", - 81, - 450, - 25, - Color::RED, - ); - raylib.draw_text( - - "QUIT", - 79, - 450, - 25, - Color::BLUE, - ); - raylib.draw_text( - - "QUIT", - 80, - 450, - 25, - Color::WHITE, - ); - - - } + let hovering_quit = + Rectangle::new(80.0, 445.0, 65.0, 20.0).check_collision_point_rec(mouse_position); + raylib.draw_rgb_split_text( + Vector2::new(80.0, 450.0), + "QUIT", + 25, + hovering_quit, + Color::WHITE, + ); + self.is_quit_pressed = mouse_pressed && hovering_quit; } } diff --git a/game/src/scenes/mod.rs b/game/src/scenes/mod.rs index 3221362..ad0787c 100644 --- a/game/src/scenes/mod.rs +++ b/game/src/scenes/mod.rs @@ -2,7 +2,6 @@ use self::{ pause_screen::PauseScreen, fsm_error_screen::FsmErrorScreen, ingame_scene::{level::loader::load_all_levels, InGameScreen}, - loading_screen::LoadingScreen, main_menu_screen::MainMenuScreen, options_screen::OptionsScreen, how_to_play_screen::HowToPlayScreen, }; use crate::{ @@ -17,7 +16,6 @@ use raylib::{texture::Texture2D, RaylibThread}; 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; @@ -28,7 +26,6 @@ pub mod pause_screen; pub enum Scenes { #[default] FsmErrorScreen, - LoadingScreen, MainMenuScreen, InGameScene, HowToPlayScreen, @@ -62,10 +59,6 @@ pub fn build_screen_state_machine( // Set up the state machine let mut machine = StateMachine::new(); machine.add_action(Scenes::FsmErrorScreen, FsmErrorScreen::new())?; - machine.add_action( - Scenes::LoadingScreen, - LoadingScreen::new(raylib_handle, thread)?, - )?; machine.add_action(Scenes::MainMenuScreen, MainMenuScreen::new())?; machine.add_action(Scenes::HowToPlayScreen, HowToPlayScreen::new())?; machine.add_action(Scenes::OptionsScreen, OptionsScreen::new())?; diff --git a/game/src/scenes/options_screen.rs b/game/src/scenes/options_screen.rs index bf51602..84a9a40 100644 --- a/game/src/scenes/options_screen.rs +++ b/game/src/scenes/options_screen.rs @@ -5,27 +5,31 @@ use dirty_fsm::{Action, ActionFlag}; use pkg_version::pkg_version_major; use raylib::prelude::*; -use crate::{GameConfig, context::GameContext, utilities::{ +use crate::{ + 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, - }}; + }, + GameConfig, +}; use super::{Scenes, ScreenError}; use tracing::{debug, info, trace}; #[derive(Debug)] pub struct OptionsScreen { - is_btm_pressed: bool //Is back to menu button pressed + 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 + is_btm_pressed: false, } } } @@ -52,8 +56,7 @@ impl Action for OptionsScreen { if self.is_btm_pressed { Ok(ActionFlag::SwitchState(Scenes::MainMenuScreen)) - } - else{ + } else { Ok(ActionFlag::Continue) } } @@ -69,11 +72,19 @@ impl ScreenSpaceRender for OptionsScreen { fn render_screen_space( &mut self, raylib: &mut crate::utilities::non_ref_raylib::HackedRaylibHandle, - config: &GameConfig + config: &GameConfig, ) { + let screen_size = raylib.get_screen_size(); // Render the background raylib.clear_background(Color::BLACK); + raylib.draw_rectangle_lines( + 0, + 0, + screen_size.x as i32, + screen_size.y as i32, + config.colors.white, + ); let screen_size = raylib.get_screen_size(); @@ -82,90 +93,19 @@ impl ScreenSpaceRender for OptionsScreen { 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, - ); + // Render the title + raylib.draw_rgb_split_text(Vector2::new(40.0, 80.0), "Options", 70, true, 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, - ); - } + let hovering_back = Rectangle::new(35.0, screen_size.y as f32 - 80.0, 200.0, 40.0) + .check_collision_point_rec(mouse_position); + raylib.draw_rgb_split_text( + Vector2::new(25.0, screen_size.y - 50.0), + "Options", + 25, + hovering_back, + Color::WHITE, + ); + self.is_btm_pressed = mouse_pressed && hovering_back; } } diff --git a/game/src/scenes/pause_screen.rs b/game/src/scenes/pause_screen.rs index 04c0bac..1dde2e6 100644 --- a/game/src/scenes/pause_screen.rs +++ b/game/src/scenes/pause_screen.rs @@ -59,6 +59,13 @@ impl Action for PauseScreen { ) -> Result, ScreenError> { trace!("execute() called on PauseScreen"); self.render_screen_space(&mut context.renderer.borrow_mut(), &context.config); + //Screen Size + let screen_size = context.renderer.borrow_mut().get_screen_size(); + + let centered_x_menu = (screen_size.x as f32 / 2.0) - 120.0; + let centered_y_menu = (screen_size.y as f32 / 2.0) + 100.0; + let centered_x_paused = (screen_size.x as f32 / 2.0) - 220.0; + let centered_y_paused = (screen_size.y as f32 / 2.0) - 40.0; //Mouse Position let mouse_position: Vector2 = context.renderer.borrow_mut().get_mouse_position(); @@ -69,14 +76,18 @@ impl Action for PauseScreen { .is_mouse_button_down(MouseButton::MOUSE_LEFT_BUTTON); //"Hitboxes" for the resume and Main menu buttons + + //For Paused if is_left_click - && Rectangle::new(322.0, 321.0, 435.0, 80.0).check_collision_point_rec(mouse_position) + && Rectangle::new(centered_x_paused, centered_y_paused, 435.0, 80.0) + .check_collision_point_rec(mouse_position) { return Ok(ActionFlag::SwitchState(Scenes::InGameScene)); } - + //For Menu if is_left_click - && Rectangle::new(390.0, 464.0, 200.0, 50.0).check_collision_point_rec(mouse_position) + && Rectangle::new(centered_x_menu, centered_y_menu, 200.0, 50.0) + .check_collision_point_rec(mouse_position) { return Ok(ActionFlag::SwitchState(Scenes::MainMenuScreen)); } @@ -114,89 +125,45 @@ impl ScreenSpaceRender for PauseScreen { //Mouse Input let is_left_click = raylib.is_mouse_button_down(MouseButton::MOUSE_LEFT_BUTTON); + raylib.draw_rectangle_lines( + 0, + 0, + screen_size.x as i32, + screen_size.y as i32, + config.colors.white, + ); + + //Variables for centering + let centered_x_menu = (screen_size.x as f32 / 2.0) - 120.0; + let centered_y_menu = (screen_size.y as f32 / 2.0) + 100.0; + let centered_x_paused = (screen_size.x as f32 / 2.0) - 220.0; + let centered_y_paused = (screen_size.y as f32 / 2.0) - 40.0; + //Pause Menu Texts With Glitchy Effect - raylib.draw_text( + let hovering_pause = Rectangle::new(centered_x_paused, centered_y_paused, 435.0, 80.0) + .check_collision_point_rec(mouse_position); + raylib.draw_rgb_split_text( + Vector2::new((screen_size.x / 2.0) - 220.0, (screen_size.y / 2.0) - 40.0), "Paused", - (screen_size.x as i32 / 2) - 223, - (screen_size.y as i32 / 2) - 40, - 120, - Color::RED, - ); - raylib.draw_text( - "Paused", - (screen_size.x as i32 / 2) - 217, - (screen_size.y as i32 / 2) - 40, - 120, - Color::BLUE, - ); - raylib.draw_text( - "Paused", - (screen_size.x as i32 / 2) - 220, - (screen_size.y as i32 / 2) - 40, 120, + hovering_pause, Color::WHITE, ); - raylib.draw_text( + raylib.draw_rgb_split_text( + Vector2::new((screen_size.x / 2.0) - 80.0, (screen_size.y / 2.0) + 60.0), "Click To Resume", - (screen_size.x as i32 / 2) - 80, - (screen_size.y as i32 / 2) + 60, - 20, - Color::RED, - ); - raylib.draw_text( - "Click To Resume", - (screen_size.x as i32 / 2) - 80, - (screen_size.y as i32 / 2) + 60, - 20, - Color::BLUE, - ); - raylib.draw_text( - "Click To Resume", - (screen_size.x as i32 / 2) - 80, - (screen_size.y as i32 / 2) + 60, 20, + false, Color::WHITE, ); - raylib.draw_text( + let hovering_main_menu = Rectangle::new(centered_x_menu, centered_y_menu, 200.0, 50.0) + .check_collision_point_rec(mouse_position); + raylib.draw_rgb_split_text( + Vector2::new((screen_size.x / 2.0) - 120.0, (screen_size.y / 2.0) + 100.0), "Main Menu", - (screen_size.x as i32 / 2) - 123, - (screen_size.y as i32 / 2) + 100, - 50, - Color::RED, - ); - raylib.draw_text( - "Main Menu", - (screen_size.x as i32 / 2) - 117, - (screen_size.y as i32 / 2) + 100, - 50, - Color::BLUE, - ); - raylib.draw_text( - "Main Menu", - (screen_size.x as i32 / 2) - 120, - (screen_size.y as i32 / 2) + 100, 50, + hovering_main_menu, Color::WHITE, ); - - if Rectangle::new(390.0, 464.0, 200.0, 50.0).check_collision_point_rec(mouse_position) { - raylib.draw_text( - "Main Menu", - (screen_size.x as i32 / 2) - 120, - (screen_size.y as i32 / 2) + 100, - 50, - Color::YELLOW, - ); - } - - if Rectangle::new(322.0, 321.0, 435.0, 80.0).check_collision_point_rec(mouse_position) { - raylib.draw_text( - "Paused", - (screen_size.x as i32 / 2) - 220, - (screen_size.y as i32 / 2) - 40, - 120, - Color::DARKBLUE, - ); - } } } diff --git a/game/src/utilities/non_ref_raylib.rs b/game/src/utilities/non_ref_raylib.rs index 7dbd3f9..1ce7051 100644 --- a/game/src/utilities/non_ref_raylib.rs +++ b/game/src/utilities/non_ref_raylib.rs @@ -1,12 +1,12 @@ use std::ops::{Deref, DerefMut}; +use raylib::prelude::*; use raylib::{math::Vector2, prelude::RaylibDraw, RaylibHandle}; #[derive(Debug)] pub struct HackedRaylibHandle(RaylibHandle); impl HackedRaylibHandle { - /// Get the screen size as a vector #[inline] pub fn get_screen_size(&self) -> Vector2 { @@ -15,6 +15,33 @@ impl HackedRaylibHandle { self.get_screen_height() as f32, ) } + + #[inline] + pub fn draw_rgb_split_text( + &mut self, + position: Vector2, + text: &str, + font_size: i32, + hovering: bool, + color: Color, + ) { + let extra_smudge = if hovering { 2 } else { 0 }; + self.draw_text( + text, + position.x as i32 - 1 - extra_smudge, + position.y as i32, + font_size, + Color::BLUE, + ); + self.draw_text( + text, + position.x as i32 + 1 + extra_smudge, + position.y as i32, + font_size, + Color::RED, + ); + self.draw_text(text, position.x as i32, position.y as i32, font_size, color); + } } impl RaylibDraw for HackedRaylibHandle {}