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

View File

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

View File

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

View File

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

View File

@@ -11,7 +11,7 @@ pub mod emscripten;
/// Platform abstraction trait that defines cross-platform functionality. /// Platform abstraction trait that defines cross-platform functionality.
pub trait Platform { pub trait Platform {
/// Sleep for the specified duration using platform-appropriate method. /// 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. /// Get the current time in seconds since some reference point.
/// This is available for future use in timing and performance monitoring. /// This is available for future use in timing and performance monitoring.