Merge pull request #5 from Ewpratten/ewpratten/rendering_basics
Bring in a basic event loop
This commit is contained in:
commit
542fce1ded
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@ -1,3 +1,7 @@
|
|||||||
{
|
{
|
||||||
"git.detectSubmodules": false
|
"git.detectSubmodules": false,
|
||||||
|
"cSpell.words": [
|
||||||
|
"msaa",
|
||||||
|
"vsync"
|
||||||
|
]
|
||||||
}
|
}
|
12
README.md
12
README.md
@ -1,9 +1,6 @@
|
|||||||
# Ludum Dare 50: *unnamed game*
|
# Ludum Dare 50: *unnamed game*
|
||||||
[](https://github.com/Ewpratten/ludum-dare-50/actions/workflows/build.yml)
|
[](https://github.com/Ewpratten/ludum-dare-50/actions/workflows/build.yml)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Cloning
|
## Cloning
|
||||||
|
|
||||||
**IMPORTANT:** This project makes use of recursive submodules. Make sure to pull them via GitKracken, or with the following command:
|
**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
|
```sh
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
```
|
```
|
||||||
|
|
||||||
*Your builds will fail unless this is done*
|
*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
|
||||||
|
```
|
||||||
|
@ -8,4 +8,9 @@ pub struct Args {
|
|||||||
/// Use verbose logging
|
/// Use verbose logging
|
||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
pub verbose: bool,
|
pub verbose: bool,
|
||||||
|
|
||||||
|
/// Force re-create the settings and savestate files
|
||||||
|
#[clap( long)]
|
||||||
|
pub force_recreate_savefiles: bool,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ use clap::StructOpt;
|
|||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
|
|
||||||
mod cli;
|
mod cli;
|
||||||
mod logging;
|
|
||||||
mod debug_profiling;
|
mod debug_profiling;
|
||||||
|
mod logging;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
@ -30,6 +30,6 @@ async fn main() {
|
|||||||
|
|
||||||
// Start the game
|
// Start the game
|
||||||
log::info!("Starting game");
|
log::info!("Starting game");
|
||||||
game_logic::entrypoint().await;
|
game_logic::entrypoint(args.force_recreate_savefiles).await;
|
||||||
log::info!("Goodbye!");
|
log::info!("Goodbye!");
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,32 @@
|
|||||||
//! This file is the main entry point for the game logic.
|
//! This file is the main entry point for the game logic.
|
||||||
|
|
||||||
|
use std::borrow::Borrow;
|
||||||
|
|
||||||
pub(crate) mod persistent;
|
pub(crate) mod persistent;
|
||||||
|
pub(crate) mod rendering;
|
||||||
|
|
||||||
/// This is the game logic entrypoint. Despite being async,
|
/// This is the game logic entrypoint. Despite being async,
|
||||||
/// this is expected to block the main thread for rendering and stuff.
|
/// 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.");
|
log::info!("Game main thread handed off to logic crate.");
|
||||||
|
|
||||||
// Load the game settings
|
// 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?");
|
.expect("Failed to parse game settings from disk. Possibly corrupt file?");
|
||||||
|
|
||||||
// Load the game save state
|
// 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?");
|
.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
|
// Clean up any resources
|
||||||
settings
|
settings
|
||||||
|
@ -42,7 +42,7 @@ impl GameSaveState {
|
|||||||
|
|
||||||
/// Loads the savestate from disk.
|
/// Loads the savestate from disk.
|
||||||
#[profiling::function]
|
#[profiling::function]
|
||||||
pub fn load_or_create() -> Result<Self, serde_json::Error> {
|
pub fn load_or_create(force_create: bool) -> Result<Self, serde_json::Error> {
|
||||||
// Attempt to load the savestate from the save location.
|
// Attempt to load the savestate from the save location.
|
||||||
let save_location = Self::get_save_location();
|
let save_location = Self::get_save_location();
|
||||||
log::debug!(
|
log::debug!(
|
||||||
@ -50,7 +50,7 @@ impl GameSaveState {
|
|||||||
save_location.display()
|
save_location.display()
|
||||||
);
|
);
|
||||||
|
|
||||||
if save_location.is_file() {
|
if save_location.is_file() && !force_create {
|
||||||
log::debug!("Found existing savestate file.");
|
log::debug!("Found existing savestate file.");
|
||||||
return serde_json::from_str(std::fs::read_to_string(&save_location).unwrap().as_str());
|
return serde_json::from_str(std::fs::read_to_string(&save_location).unwrap().as_str());
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,14 @@ use serde::{Deserialize, Serialize};
|
|||||||
/// Please don't add anything relating to gameplay though (no coins, health, etc.).
|
/// Please don't add anything relating to gameplay though (no coins, health, etc.).
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct PersistentGameSettings {
|
pub struct PersistentGameSettings {
|
||||||
// TODO: Add settings here.
|
/// The target framerate for the game
|
||||||
|
pub target_fps: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add any default values here.
|
// Add any default values here.
|
||||||
impl Default for PersistentGameSettings {
|
impl Default for PersistentGameSettings {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {}
|
Self { target_fps: 60 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +44,7 @@ impl PersistentGameSettings {
|
|||||||
|
|
||||||
/// Loads the settings from disk.
|
/// Loads the settings from disk.
|
||||||
#[profiling::function]
|
#[profiling::function]
|
||||||
pub fn load_or_create() -> Result<Self, serde_json::Error> {
|
pub fn load_or_create(force_create: bool) -> Result<Self, serde_json::Error> {
|
||||||
// Attempt to load the settings from the save location.
|
// Attempt to load the settings from the save location.
|
||||||
let save_location = Self::get_save_location();
|
let save_location = Self::get_save_location();
|
||||||
log::debug!(
|
log::debug!(
|
||||||
@ -51,7 +52,7 @@ impl PersistentGameSettings {
|
|||||||
save_location.display()
|
save_location.display()
|
||||||
);
|
);
|
||||||
|
|
||||||
if save_location.is_file() {
|
if save_location.is_file() && !force_create {
|
||||||
log::debug!("Found existing settings file.");
|
log::debug!("Found existing settings file.");
|
||||||
return serde_json::from_str(std::fs::read_to_string(&save_location).unwrap().as_str());
|
return serde_json::from_str(std::fs::read_to_string(&save_location).unwrap().as_str());
|
||||||
}
|
}
|
||||||
|
20
game/game_logic/src/rendering/event_loop.rs
Normal file
20
game/game_logic/src/rendering/event_loop.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use raylib::RaylibBuilder;
|
||||||
|
|
||||||
|
pub fn handle_graphics_blocking<ConfigBuilder>(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() {}
|
||||||
|
}
|
3
game/game_logic/src/rendering/mod.rs
Normal file
3
game/game_logic/src/rendering/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
//! This module contains lower level rendering logic.
|
||||||
|
|
||||||
|
pub mod event_loop;
|
0
game/game_logic/src/rendering/utilities/mod.rs
Normal file
0
game/game_logic/src/rendering/utilities/mod.rs
Normal file
Reference in New Issue
Block a user