From fdf4b5c82ccb1d30983210a350576b9b3156fbbc Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 17 Mar 2022 16:48:10 -0400 Subject: [PATCH 1/2] Allow blank window rendering --- .vscode/settings.json | 6 +++++- game/game_logic/src/lib.rs | 11 +++++++++- game/game_logic/src/persistent/settings.rs | 5 +++-- game/game_logic/src/rendering/event_loop.rs | 20 +++++++++++++++++++ game/game_logic/src/rendering/mod.rs | 3 +++ .../game_logic/src/rendering/utilities/mod.rs | 0 6 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 game/game_logic/src/rendering/event_loop.rs create mode 100644 game/game_logic/src/rendering/mod.rs create mode 100644 game/game_logic/src/rendering/utilities/mod.rs diff --git a/.vscode/settings.json b/.vscode/settings.json index 93dc280f..6f61c03a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,7 @@ { - "git.detectSubmodules": false + "git.detectSubmodules": false, + "cSpell.words": [ + "msaa", + "vsync" + ] } \ No newline at end of file diff --git a/game/game_logic/src/lib.rs b/game/game_logic/src/lib.rs index b1f9531b..414832f0 100644 --- a/game/game_logic/src/lib.rs +++ b/game/game_logic/src/lib.rs @@ -1,6 +1,9 @@ //! This file is the main entry point for the game logic. +use std::borrow::Borrow; + pub(crate) mod persistent; +pub(crate) mod rendering; /// This is the game logic entrypoint. Despite being async, /// this is expected to block the main thread for rendering and stuff. @@ -15,7 +18,13 @@ pub async fn entrypoint() { let mut save_state = persistent::save_state::GameSaveState::load_or_create() .expect("Failed to parse game save state from disk. Possibly corrupt file?"); - // TODO: Blocking game loop goes here + // Blocking call to the graphics rendering loop. + rendering::event_loop::handle_graphics_blocking( + |builder| { + builder.msaa_4x().vsync(); + }, + settings.target_fps, + ); // Clean up any resources settings diff --git a/game/game_logic/src/persistent/settings.rs b/game/game_logic/src/persistent/settings.rs index 6d2e7268..f74b33d3 100644 --- a/game/game_logic/src/persistent/settings.rs +++ b/game/game_logic/src/persistent/settings.rs @@ -9,13 +9,14 @@ use serde::{Deserialize, Serialize}; /// Please don't add anything relating to gameplay though (no coins, health, etc.). #[derive(Debug, Clone, Serialize, Deserialize)] pub struct PersistentGameSettings { - // TODO: Add settings here. + /// The target framerate for the game + pub target_fps: u32, } // Add any default values here. impl Default for PersistentGameSettings { fn default() -> Self { - Self {} + Self { target_fps: 60 } } } diff --git a/game/game_logic/src/rendering/event_loop.rs b/game/game_logic/src/rendering/event_loop.rs new file mode 100644 index 00000000..cfb693a3 --- /dev/null +++ b/game/game_logic/src/rendering/event_loop.rs @@ -0,0 +1,20 @@ +use raylib::RaylibBuilder; + +pub fn handle_graphics_blocking(config: ConfigBuilder, target_frames_per_second: u32) +where + ConfigBuilder: FnOnce(&mut RaylibBuilder), +{ + // Let the caller configure Raylib's internal window stuff + let (mut raylib_handle, raylib_thread) = { + let mut builder = raylib::init(); + config(&mut builder); + builder.build() + }; + + // Set some important settings on the window + raylib_handle.set_exit_key(None); + raylib_handle.set_target_fps(target_frames_per_second); + + // Run the event loop + while !raylib_handle.window_should_close() {} +} diff --git a/game/game_logic/src/rendering/mod.rs b/game/game_logic/src/rendering/mod.rs new file mode 100644 index 00000000..84cb5be0 --- /dev/null +++ b/game/game_logic/src/rendering/mod.rs @@ -0,0 +1,3 @@ +//! This module contains lower level rendering logic. + +pub mod event_loop; \ No newline at end of file diff --git a/game/game_logic/src/rendering/utilities/mod.rs b/game/game_logic/src/rendering/utilities/mod.rs new file mode 100644 index 00000000..e69de29b From dd0f27fd1e1797981b797046280a0eb0f8f34720 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 17 Mar 2022 21:57:52 -0400 Subject: [PATCH 2/2] Fix a bug with file recreation --- README.md | 12 ++++++++---- game/desktop_wrapper/src/cli.rs | 5 +++++ game/desktop_wrapper/src/main.rs | 4 ++-- game/game_logic/src/lib.rs | 8 +++++--- game/game_logic/src/persistent/save_state.rs | 4 ++-- game/game_logic/src/persistent/settings.rs | 4 ++-- 6 files changed, 24 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 92a4b1e3..d33fb03b 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,6 @@ # Ludum Dare 50: *unnamed game* [![Build Full Release](https://github.com/Ewpratten/ludum-dare-50/actions/workflows/build.yml/badge.svg)](https://github.com/Ewpratten/ludum-dare-50/actions/workflows/build.yml) - - - ## Cloning **IMPORTANT:** This project makes use of recursive submodules. Make sure to pull them via GitKracken, or with the following command: @@ -11,5 +8,12 @@ ```sh git submodule update --init --recursive ``` - *Your builds will fail unless this is done* + +## Development notes + +When working on the settings and savestate file code, there is a chance you will corrupt your save files. If this happens, launch the game with the following command to fix them: + +```sh +cargo run -- --force-recreate-savefiles +``` diff --git a/game/desktop_wrapper/src/cli.rs b/game/desktop_wrapper/src/cli.rs index 54acbd35..1f58deab 100644 --- a/game/desktop_wrapper/src/cli.rs +++ b/game/desktop_wrapper/src/cli.rs @@ -8,4 +8,9 @@ pub struct Args { /// Use verbose logging #[clap(short, long)] pub verbose: bool, + + /// Force re-create the settings and savestate files + #[clap( long)] + pub force_recreate_savefiles: bool, + } diff --git a/game/desktop_wrapper/src/main.rs b/game/desktop_wrapper/src/main.rs index 4399a1df..7120a73a 100644 --- a/game/desktop_wrapper/src/main.rs +++ b/game/desktop_wrapper/src/main.rs @@ -7,8 +7,8 @@ use clap::StructOpt; use log::LevelFilter; mod cli; -mod logging; mod debug_profiling; +mod logging; #[tokio::main] async fn main() { @@ -30,6 +30,6 @@ async fn main() { // Start the game log::info!("Starting game"); - game_logic::entrypoint().await; + game_logic::entrypoint(args.force_recreate_savefiles).await; log::info!("Goodbye!"); } diff --git a/game/game_logic/src/lib.rs b/game/game_logic/src/lib.rs index 414832f0..40bb8190 100644 --- a/game/game_logic/src/lib.rs +++ b/game/game_logic/src/lib.rs @@ -7,15 +7,17 @@ pub(crate) mod rendering; /// This is the game logic entrypoint. Despite being async, /// this is expected to block the main thread for rendering and stuff. -pub async fn entrypoint() { +/// +/// Setting `force_recreate_savefiles` will cause the game to recreate its settings and savestate files. +pub async fn entrypoint(force_recreate_savefiles: bool) { log::info!("Game main thread handed off to logic crate."); // Load the game settings - let mut settings = persistent::settings::PersistentGameSettings::load_or_create() + let mut settings = persistent::settings::PersistentGameSettings::load_or_create(force_recreate_savefiles) .expect("Failed to parse game settings from disk. Possibly corrupt file?"); // Load the game save state - let mut save_state = persistent::save_state::GameSaveState::load_or_create() + let mut save_state = persistent::save_state::GameSaveState::load_or_create(force_recreate_savefiles) .expect("Failed to parse game save state from disk. Possibly corrupt file?"); // Blocking call to the graphics rendering loop. diff --git a/game/game_logic/src/persistent/save_state.rs b/game/game_logic/src/persistent/save_state.rs index e364c56d..273c842c 100644 --- a/game/game_logic/src/persistent/save_state.rs +++ b/game/game_logic/src/persistent/save_state.rs @@ -42,7 +42,7 @@ impl GameSaveState { /// Loads the savestate from disk. #[profiling::function] - pub fn load_or_create() -> Result { + pub fn load_or_create(force_create: bool) -> Result { // Attempt to load the savestate from the save location. let save_location = Self::get_save_location(); log::debug!( @@ -50,7 +50,7 @@ impl GameSaveState { save_location.display() ); - if save_location.is_file() { + if save_location.is_file() && !force_create { log::debug!("Found existing savestate file."); return serde_json::from_str(std::fs::read_to_string(&save_location).unwrap().as_str()); } diff --git a/game/game_logic/src/persistent/settings.rs b/game/game_logic/src/persistent/settings.rs index 0b2d07c0..4b588d20 100644 --- a/game/game_logic/src/persistent/settings.rs +++ b/game/game_logic/src/persistent/settings.rs @@ -44,7 +44,7 @@ impl PersistentGameSettings { /// Loads the settings from disk. #[profiling::function] - pub fn load_or_create() -> Result { + pub fn load_or_create(force_create: bool) -> Result { // Attempt to load the settings from the save location. let save_location = Self::get_save_location(); log::debug!( @@ -52,7 +52,7 @@ impl PersistentGameSettings { save_location.display() ); - if save_location.is_file() { + if save_location.is_file() && !force_create { log::debug!("Found existing settings file."); return serde_json::from_str(std::fs::read_to_string(&save_location).unwrap().as_str()); }