diff --git a/solitaire_app/src/lib.rs b/solitaire_app/src/lib.rs index 2300891..7acdd7b 100644 --- a/solitaire_app/src/lib.rs +++ b/solitaire_app/src/lib.rs @@ -172,13 +172,16 @@ fn build_app_with_settings( // a 1-second ceiling when the app is backgrounded cuts wake-up frequency // from ~60 Hz to ≤1 Hz, dramatically reducing background battery drain. // - // The focused mode stays Continuous so that card-slide animations remain - // smooth. PresentMode::AutoVsync (set above) keeps the GPU capped at the - // display refresh rate (~60 Hz) when foregrounded, which already prevents - // the GPU from spinning at 200+ fps between vsync intervals. + // focused_mode uses reactive_low_power(100 ms) so the CPU only wakes when + // an event arrives (touch, resize, etc.) or an animation system writes + // RequestRedraw. The 100 ms ceiling is a fallback that ensures the game + // timer ticks at least 10×/s even with no input, while keeping the GPU + // completely idle between frames when the board is static. + // PresentMode::AutoVsync (set above) still caps the GPU at the display + // refresh rate when frames do render. #[cfg(target_os = "android")] app.insert_resource(WinitSettings { - focused_mode: UpdateMode::Continuous, + focused_mode: UpdateMode::reactive_low_power(std::time::Duration::from_millis(100)), unfocused_mode: UpdateMode::reactive_low_power(std::time::Duration::from_secs(1)), }); diff --git a/solitaire_engine/src/animation_plugin.rs b/solitaire_engine/src/animation_plugin.rs index 438f0af..ae2073a 100644 --- a/solitaire_engine/src/animation_plugin.rs +++ b/solitaire_engine/src/animation_plugin.rs @@ -13,6 +13,7 @@ use std::collections::VecDeque; use bevy::prelude::*; +use bevy::window::RequestRedraw; use solitaire_data::{AnimSpeed, Settings}; use crate::achievement_plugin::display_name_for; @@ -180,6 +181,7 @@ impl Plugin for AnimationPlugin { .add_message::() .add_message::() .add_message::() + .add_message::() .init_resource::() .init_resource::() .init_resource::() diff --git a/solitaire_engine/src/auto_complete_plugin.rs b/solitaire_engine/src/auto_complete_plugin.rs index 2c06f2e..fa74ab1 100644 --- a/solitaire_engine/src/auto_complete_plugin.rs +++ b/solitaire_engine/src/auto_complete_plugin.rs @@ -9,6 +9,7 @@ //! returns `None` (e.g. a transient state), the plugin retries next tick. use bevy::prelude::*; +use bevy::window::RequestRedraw; use crate::audio_plugin::{AudioState, SoundLibrary}; use crate::events::{MoveRequestEvent, StateChangedEvent}; @@ -39,7 +40,9 @@ pub struct AutoCompletePlugin; impl Plugin for AutoCompletePlugin { fn build(&self, app: &mut App) { - app.init_resource::().add_systems( + app.init_resource::() + .add_message::() + .add_systems( Update, ( detect_auto_complete, diff --git a/solitaire_engine/src/card_animation/mod.rs b/solitaire_engine/src/card_animation/mod.rs index f21983c..45d454c 100644 --- a/solitaire_engine/src/card_animation/mod.rs +++ b/solitaire_engine/src/card_animation/mod.rs @@ -92,6 +92,7 @@ pub use timing::{ pub use tuning::{AnimationTuning, InputPlatform}; use bevy::prelude::*; +use bevy::window::RequestRedraw; use crate::card_plugin::CardEntity; use crate::events::{DrawRequestEvent, GameWonEvent, MoveRequestEvent, UndoRequestEvent}; @@ -125,6 +126,7 @@ impl Plugin for CardAnimationPlugin { .add_message::() .add_message::() .add_message::() + .add_message::() .init_resource::() .init_resource::() .init_resource::() diff --git a/solitaire_engine/src/feedback_anim_plugin.rs b/solitaire_engine/src/feedback_anim_plugin.rs index eb48225..d18a07b 100644 --- a/solitaire_engine/src/feedback_anim_plugin.rs +++ b/solitaire_engine/src/feedback_anim_plugin.rs @@ -42,6 +42,7 @@ use std::f32::consts::PI; use std::hash::{Hash, Hasher}; use bevy::prelude::*; +use bevy::window::RequestRedraw; use solitaire_core::pile::PileType; use solitaire_data::AnimSpeed; @@ -204,6 +205,7 @@ impl Plugin for FeedbackAnimPlugin { .add_message::() .add_message::() .add_message::() + .add_message::() .add_systems( Update, (