feat: avoid using spin sleep unless focused

This commit is contained in:
2025-08-13 21:36:06 -05:00
parent d80d7061e7
commit 12a63374a8
5 changed files with 22 additions and 18 deletions

View File

@@ -6,7 +6,7 @@ use sdl2::render::{Canvas, ScaleMode, Texture, TextureCreator};
use sdl2::ttf::Sdl2TtfContext;
use sdl2::video::{Window, WindowContext};
use sdl2::{AudioSubsystem, EventPump, Sdl, VideoSubsystem};
use tracing::{error, event};
use tracing::{debug, error, info, warn};
use crate::error::{GameError, GameResult};
@@ -23,6 +23,7 @@ pub struct App {
event_pump: &'static mut EventPump,
backbuffer: Texture<'static>,
paused: bool,
focused: bool,
last_tick: Instant,
cursor_pos: Vec2,
}
@@ -87,6 +88,7 @@ impl App {
event_pump,
backbuffer,
paused: false,
focused: true,
last_tick: Instant::now(),
cursor_pos: Vec2::ZERO,
})
@@ -99,18 +101,19 @@ impl App {
for event in self.event_pump.poll_iter() {
match event {
Event::Window { win_event, .. } => match win_event {
WindowEvent::Hidden => {
event!(tracing::Level::DEBUG, "Window hidden");
WindowEvent::FocusGained => {
self.focused = true;
}
WindowEvent::Shown => {
event!(tracing::Level::DEBUG, "Window shown");
WindowEvent::FocusLost => {
debug!("Window focus lost");
self.focused = false;
}
_ => {}
},
// It doesn't really make sense to have this available in the browser
#[cfg(not(target_os = "emscripten"))]
Event::Quit { .. } => {
event!(tracing::Level::INFO, "Exit requested. Exiting...");
info!("Exit requested. Exiting...");
return false;
}
Event::MouseMotion { x, y, .. } => {
@@ -124,12 +127,12 @@ impl App {
for command in commands {
match command {
GameCommand::Exit => {
event!(tracing::Level::INFO, "Exit requested. Exiting...");
info!("Exit requested. Exiting...");
return false;
}
GameCommand::TogglePause => {
self.paused = !self.paused;
event!(tracing::Level::INFO, "{}", if self.paused { "Paused" } else { "Unpaused" });
info!("{}", if self.paused { "Paused" } else { "Unpaused" });
}
_ => self.game.post_event(command.into()),
}
@@ -155,14 +158,10 @@ impl App {
if start.elapsed() < LOOP_TIME {
let time = LOOP_TIME.saturating_sub(start.elapsed());
if time != Duration::ZERO {
get_platform().sleep(time);
get_platform().sleep(time, self.focused);
}
} else {
event!(
tracing::Level::WARN,
"Game loop behind schedule by: {:?}",
start.elapsed() - LOOP_TIME
);
warn!("Game loop behind schedule by: {:?}", start.elapsed() - LOOP_TIME);
}
true

View File

@@ -6,6 +6,7 @@ use crate::{entity::direction::Direction, input::commands::GameCommand};
pub mod commands;
#[derive(Debug, Clone, Default)]
pub struct InputSystem {
key_bindings: HashMap<Keycode, GameCommand>,
}

View File

@@ -11,8 +11,12 @@ use crate::platform::Platform;
pub struct DesktopPlatform;
impl Platform for DesktopPlatform {
fn sleep(&self, duration: Duration) {
spin_sleep::sleep(duration);
fn sleep(&self, duration: Duration, focused: bool) {
if focused {
spin_sleep::sleep(duration);
} else {
std::thread::sleep(duration);
}
}
fn get_time(&self) -> f64 {

View File

@@ -11,7 +11,7 @@ use crate::platform::Platform;
pub struct EmscriptenPlatform;
impl Platform for EmscriptenPlatform {
fn sleep(&self, duration: Duration) {
fn sleep(&self, duration: Duration, _focused: bool) {
unsafe {
emscripten_sleep(duration.as_millis() as u32);
}

View File

@@ -11,7 +11,7 @@ pub mod emscripten;
/// Platform abstraction trait that defines cross-platform functionality.
pub trait Platform {
/// Sleep for the specified duration using platform-appropriate method.
fn sleep(&self, duration: Duration);
fn sleep(&self, duration: Duration, focused: bool);
/// Get the current time in seconds since some reference point.
/// This is available for future use in timing and performance monitoring.