72 lines
2.4 KiB
Rust
72 lines
2.4 KiB
Rust
// file: crates/engines/engine-v1-common/src/game_loop.rs
|
|
// version: 4
|
|
|
|
/// Minimal update contract implemented by a game state consumed by engine V1.
|
|
pub trait EngineGame {
|
|
/// Advances the game by one engine update using platform-independent input.
|
|
fn update(&mut self, frame: crate::EngineFrame, input: crate::InputState);
|
|
|
|
/// Handles a platform-independent request to leave the current runtime.
|
|
///
|
|
/// Games may mutate their state and return [`crate::QuitDecision::Continue`] to implement
|
|
/// pause/confirmation screens, navigation, score submission, saving, or other workflows.
|
|
fn quit_requested(&mut self, _request: crate::QuitRequest) -> crate::QuitDecision {
|
|
return crate::QuitDecision::Exit;
|
|
}
|
|
|
|
/// Produces the platform-independent scene rendered after the update.
|
|
fn scene(&self) -> crate::EngineScene {
|
|
return crate::EngineScene::empty(crate::RenderColor::rgb(18, 18, 24));
|
|
}
|
|
}
|
|
|
|
/// Deterministic fixed-step driver used before and underneath platform event loops.
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
pub struct FixedStepRunner {
|
|
delta: std::time::Duration,
|
|
next_frame_index: u64,
|
|
elapsed: std::time::Duration,
|
|
}
|
|
|
|
impl FixedStepRunner {
|
|
/// Creates a fixed-step runner using the supplied update duration.
|
|
#[must_use]
|
|
pub const fn new(delta: std::time::Duration) -> Self {
|
|
return Self { delta, next_frame_index: 0, elapsed: std::time::Duration::ZERO };
|
|
}
|
|
|
|
/// Returns the configured fixed update duration.
|
|
#[must_use]
|
|
pub const fn delta(self) -> std::time::Duration {
|
|
return self.delta;
|
|
}
|
|
|
|
/// Returns the index that will be assigned to the next update.
|
|
#[must_use]
|
|
pub const fn next_frame_index(self) -> u64 {
|
|
return self.next_frame_index;
|
|
}
|
|
|
|
/// Returns the accumulated simulated time.
|
|
#[must_use]
|
|
pub const fn elapsed(self) -> std::time::Duration {
|
|
return self.elapsed;
|
|
}
|
|
|
|
/// Advances one game state by one deterministic update.
|
|
pub fn tick<G>(&mut self, game: &mut G, input: crate::InputState)
|
|
where
|
|
G: crate::EngineGame,
|
|
{
|
|
let frame = crate::EngineFrame::new(self.next_frame_index, self.delta, self.elapsed);
|
|
game.update(frame, input);
|
|
self.next_frame_index = self.next_frame_index.saturating_add(1);
|
|
self.elapsed = self.elapsed.saturating_add(self.delta);
|
|
return;
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[path = "../unit_tests/game_loop.rs"]
|
|
mod tests;
|