diff --git a/solitaire_engine/src/hud_plugin/fx.rs b/solitaire_engine/src/hud_plugin/fx.rs new file mode 100644 index 0000000..a525a40 --- /dev/null +++ b/solitaire_engine/src/hud_plugin/fx.rs @@ -0,0 +1,430 @@ +//! HUD feedback effects: action-bar fades, score pulses and floaters, +//! and streak flourishes. + +use super::*; + + + +/// Auto-fade state for the action button bar. The bar fades out when +/// the cursor is in the play area (below the HUD band) and back in when +/// the cursor approaches the top of the window — same UX as a video +/// player's auto-hide controls. Buttons remain fully interactive when +/// visible; when faded out they're geometrically out of cursor reach +/// (hover requires the cursor to be on a button), so no extra +/// pointer-events guard is needed. +#[derive(Resource, Debug, Clone, Copy)] +pub struct HudActionFade { + /// Currently displayed alpha. Lerped toward `target` each frame. + pub alpha: f32, + /// Where `alpha` is heading — 0.0 (faded out) or 1.0 (visible). + pub target: f32, +} + +impl Default for HudActionFade { + fn default() -> Self { + // Start visible so the player sees the controls on first launch + // before they've moved the cursor anywhere. + Self { + alpha: 1.0, + target: 1.0, + } + } +} + +/// How many pixels from the bottom edge the cursor must be to reveal the bar. +/// Set slightly taller than `HUD_BAND_HEIGHT` so the bar fades in as the +/// cursor approaches, not only when it crosses into the band itself. +#[cfg(not(target_os = "android"))] +const ACTION_FADE_REVEAL_PX: f32 = HUD_BAND_HEIGHT + 32.0; + +/// Lerp rate for fading (per second). 6.0 ≈ 167 ms for a full +/// transition — fast enough to feel responsive without flashing on +/// brief cursor wanders into the reveal zone. +#[cfg(not(target_os = "android"))] +const ACTION_FADE_RATE_PER_SEC: f32 = 6.0; + +/// Updates the fade state from cursor position. Sets `target = 1.0` if +/// the cursor is in the reveal zone (bottom of window) or off-screen +/// (player is using keyboard); `0.0` otherwise. Lerps `alpha` toward +/// `target` at a fixed rate so the visual transition is smooth across +/// variable framerates. +#[cfg(not(target_os = "android"))] +pub(super) fn update_action_fade(windows: Query<&Window>, time: Res