diff --git a/.vscode/settings.json b/.vscode/settings.json index d695928..6986321 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,6 +2,7 @@ "cSpell.words": [ "clippy", "raylib", - "renderable" + "renderable", + "vergen" ] } diff --git a/game/Cargo.toml b/game/Cargo.toml index a5d48a2..531f80a 100644 --- a/game/Cargo.toml +++ b/game/Cargo.toml @@ -3,6 +3,7 @@ name = "game" publish = false version = "0.1.0" edition = "2018" +build = "build.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] @@ -24,6 +25,12 @@ sentry = "0.23" image = "0.23" tempfile = "3.2" approx = "0.5" +pkg-version = "1.0" +cfg-if = "1.0" [dev-dependencies] puffin_viewer = "0.6" + +[build-dependencies] +vergen = "5" +anyhow = "1.0" diff --git a/game/build.rs b/game/build.rs new file mode 100644 index 0000000..43e8a10 --- /dev/null +++ b/game/build.rs @@ -0,0 +1,10 @@ +use anyhow::Result; +use vergen::{Config, ShaKind, vergen}; + +fn main() -> Result<()> { + + // Reads local Git information to inject into the executable at build time + let mut config = Config::default(); + *config.git_mut().sha_kind_mut() = ShaKind::Short; + vergen(config) +} diff --git a/game/src/lib.rs b/game/src/lib.rs index 00fca29..1b630fd 100644 --- a/game/src/lib.rs +++ b/game/src/lib.rs @@ -1,5 +1,6 @@ -#![feature(plugin)] #![feature(derive_default_enum)] +#![feature(custom_inner_attributes)] +#![feature(stmt_expr_attributes)] #![deny(unsafe_code)] #![warn( clippy::all, @@ -65,7 +66,6 @@ nonstandard_style, rust_2018_idioms )] -#![feature(custom_inner_attributes)] #![clippy::msrv = "1.57.0"] use std::cell::RefCell; diff --git a/game/src/scenes/loading_screen.rs b/game/src/scenes/loading_screen.rs index 0b07a32..9833c66 100644 --- a/game/src/scenes/loading_screen.rs +++ b/game/src/scenes/loading_screen.rs @@ -73,7 +73,7 @@ impl Action for LoadingScreen { let duration = Utc::now().signed_duration_since(start_timestamp); if duration.num_seconds() >= LOADING_SCREEN_DURATION_SECONDS as i64 { info!("LoadingScreen duration reached, moving to next screen"); - Ok(ActionFlag::SwitchState(Scenes::FsmErrorScreen)) + Ok(ActionFlag::SwitchState(Scenes::MainMenuScreen)) } else { Ok(ActionFlag::Continue) } diff --git a/game/src/scenes/main_menu_screen.rs b/game/src/scenes/main_menu_screen.rs new file mode 100644 index 0000000..3135218 --- /dev/null +++ b/game/src/scenes/main_menu_screen.rs @@ -0,0 +1,83 @@ +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::{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 MainMenuScreen {} + +impl MainMenuScreen { + /// Construct a new `MainMenuScreen` + pub fn new() -> Self { + Self {} + } +} + +impl Action for MainMenuScreen { + fn on_register(&mut self) -> Result<(), ScreenError> { + debug!("Registered"); + Ok(()) + } + + fn on_first_run(&mut self, _context: &GameContext) -> Result<(), ScreenError> { + debug!("Running MainMenuScreen for the first time"); + + Ok(()) + } + + fn execute( + &mut self, + _delta: &chrono::Duration, + context: &GameContext, + ) -> Result, ScreenError> { + trace!("execute() called on MainMenuScreen"); + self.render_screen_space(&mut context.renderer.borrow_mut()); + + Ok(ActionFlag::Continue) + } + + fn on_finish(&mut self, _interrupted: bool) -> Result<(), ScreenError> { + debug!("Finished MainMenuScreen"); + Ok(()) + } +} + +impl ScreenSpaceRender for MainMenuScreen { + fn render_screen_space( + &self, + raylib: &mut crate::utilities::non_ref_raylib::HackedRaylibHandle, + ) { + // Render the background + raylib.clear_background(Color::WHITE); + + // Calculate the logo position + let screen_size = raylib.get_screen_size(); + + // Only in debug mode, render a debug message + #[cfg(debug_assertions)] + { + raylib.draw_text( + "Game in DEBUG MODE. Do not redistribute!", + 10, + screen_size.y as i32 - 35, + 15, + Color::BLACK, + ); + } + // Render the game version info + raylib.draw_text( + &format!("Version: {} Commit: {}", get_version_string(), env!("VERGEN_GIT_SHA_SHORT")), + 10, + screen_size.y as i32 - 20, + 15, + Color::BLACK, + ); + } +} diff --git a/game/src/scenes/mod.rs b/game/src/scenes/mod.rs index 45262b4..ead1c54 100644 --- a/game/src/scenes/mod.rs +++ b/game/src/scenes/mod.rs @@ -1,10 +1,17 @@ +use self::{ + fsm_error_screen::FsmErrorScreen, loading_screen::LoadingScreen, + main_menu_screen::MainMenuScreen, +}; +use crate::{ + context::GameContext, + utilities::{datastore::ResourceLoadError, non_ref_raylib::HackedRaylibHandle}, +}; use dirty_fsm::StateMachine; use raylib::RaylibThread; -use crate::{context::GameContext, utilities::{datastore::ResourceLoadError, non_ref_raylib::HackedRaylibHandle}}; -use self::{fsm_error_screen::FsmErrorScreen, loading_screen::LoadingScreen}; pub mod fsm_error_screen; pub mod loading_screen; +pub mod main_menu_screen; /// Defines all scenes #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash)] @@ -12,23 +19,31 @@ pub enum Scenes { #[default] FsmErrorScreen, LoadingScreen, + MainMenuScreen, } /// Contains any possible errors thrown while rendering #[derive(Debug, Error)] pub enum ScreenError { #[error(transparent)] - ResourceLoad(#[from] ResourceLoadError) + ResourceLoad(#[from] ResourceLoadError), } /// Build the state machine for all scenes -pub fn build_screen_state_machine(raylib_handle: &mut HackedRaylibHandle, thread: &RaylibThread) -> Result< +pub fn build_screen_state_machine( + raylib_handle: &mut HackedRaylibHandle, + thread: &RaylibThread, +) -> Result< // StateMachine>)>>, StateMachine, ScreenError, > { 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::LoadingScreen, + LoadingScreen::new(raylib_handle, thread)?, + )?; + machine.add_action(Scenes::MainMenuScreen, MainMenuScreen::new())?; Ok(machine) } diff --git a/game/src/utilities/game_version.rs b/game/src/utilities/game_version.rs new file mode 100644 index 0000000..07c36a1 --- /dev/null +++ b/game/src/utilities/game_version.rs @@ -0,0 +1,25 @@ +use cfg_if::cfg_if; +use pkg_version::*; + +const GAME_VERSION_MAJOR: u32 = pkg_version_major!(); +const GAME_VERSION_MINOR: u32 = pkg_version_minor!(); +const GAME_VERSION_PATCH: u32 = pkg_version_patch!(); + +/// Get the game version as a string +#[inline] +pub fn get_version_string() -> String { + format!( + "v{}.{}.{}{}", + GAME_VERSION_MAJOR, + GAME_VERSION_MINOR, + GAME_VERSION_PATCH, + { + cfg_if! { + if #[cfg(debug_assertions)] { + "-debug" + } else { + "" + }} + } + ) +} diff --git a/game/src/utilities/mod.rs b/game/src/utilities/mod.rs index 8b856fc..1f7c03a 100644 --- a/game/src/utilities/mod.rs +++ b/game/src/utilities/mod.rs @@ -5,3 +5,4 @@ pub mod math; pub mod shaders; pub mod non_ref_raylib; pub mod render_layer; +pub mod game_version;