Skip to main content

shuyi_ui/
hurry.rs

1//! [`HurryClock`]: the time of something timed that the player can hurry by
2//! holding a key and finish with a press (ticket 2312): a text box typing
3//! out, a tally counting up, a fight played back.
4
5use crate::input::frame_seconds;
6
7/// How much faster time passes while the key is held, once it has been
8/// held for [`HURRY_DELAY`] (the text box's fast forward).
9pub const HURRY_FACTOR: f32 = 6.0;
10/// Seconds the key must be held before time passes faster, so the tap
11/// that started the step doesn't hurry it.
12pub const HURRY_DELAY: f32 = 0.3;
13
14/// The clock of one timed step: each frame's seconds as they pass, faster
15/// once the player has held the key a moment, and whether a press has
16/// skipped the step.
17///
18/// Its owner calls [`tick`](Self::tick) each frame with whether the key
19/// that hurries is held, and moves its step on by the seconds it returns.
20/// A press calls [`skip`](Self::skip), and the owner, seeing
21/// [`is_skipped`](Self::is_skipped), finishes the step at once. A new step
22/// [`reset`](Self::reset)s the clock.
23///
24/// The hold counts from the first frame the key is held, including that
25/// frame: the part of a frame past [`delay`](Self::delay) goes
26/// [`factor`](Self::factor) times as fast, the part before it as fast as
27/// ever.
28#[derive(Debug, Clone, Copy, PartialEq)]
29pub struct HurryClock {
30    /// Seconds the key must be held before time passes faster.
31    pub delay: f32,
32    /// How much faster time passes after that.
33    pub factor: f32,
34    /// Seconds the key has been held, this frame's included.
35    held_s: f32,
36    /// Whether a press has skipped the step.
37    skipped: bool,
38}
39
40impl Default for HurryClock {
41    /// The text box's: [`HURRY_DELAY`] and [`HURRY_FACTOR`].
42    fn default() -> Self {
43        Self::new(HURRY_DELAY, HURRY_FACTOR)
44    }
45}
46
47impl HurryClock {
48    /// A clock that passes time `factor` times as fast once the key has
49    /// been held `delay` seconds; nothing held, nothing skipped.
50    pub const fn new(delay: f32, factor: f32) -> Self {
51        Self {
52            delay,
53            factor,
54            held_s: 0.0,
55            skipped: false,
56        }
57    }
58
59    /// `dt` seconds on, with the key `held` or not: the seconds that pass
60    /// this frame ([`hold`](Self::hold), then [`passing`](Self::passing)).
61    pub fn tick(&mut self, dt: f32, held: bool) -> f32 {
62        self.hold(held, dt);
63        self.passing(dt)
64    }
65
66    /// Counts `dt` seconds of the key held, or, let go, starts the count
67    /// over. A `dt` that is not finite or is negative counts as 0.
68    pub fn hold(&mut self, held: bool, dt: f32) {
69        if held {
70            self.held_s += frame_seconds(dt);
71        } else {
72            self.held_s = 0.0;
73        }
74    }
75
76    /// The seconds that pass for a frame of `dt` that the key has been held
77    /// through so far: `dt`, with the part of it past the delay
78    /// [`factor`](Self::factor) times as fast. A `dt` that is not finite
79    /// or is negative counts as 0.
80    pub fn passing(&self, dt: f32) -> f32 {
81        let dt = frame_seconds(dt);
82        let fast = (self.held_s - self.delay).clamp(0.0, dt);
83        dt + fast * (self.factor - 1.0)
84    }
85
86    /// The key is no longer counted as held (the step waits on something
87    /// else), as if let go.
88    pub fn release(&mut self) {
89        self.held_s = 0.0;
90    }
91
92    /// A press finishes the step: [`is_skipped`](Self::is_skipped) until
93    /// [`reset`](Self::reset).
94    pub fn skip(&mut self) {
95        self.skipped = true;
96    }
97
98    /// Whether a press has skipped the step.
99    pub fn is_skipped(&self) -> bool {
100        self.skipped
101    }
102
103    /// A new step: nothing held, nothing skipped, the same delay and
104    /// factor.
105    pub fn reset(&mut self) {
106        self.held_s = 0.0;
107        self.skipped = false;
108    }
109}
110
111#[cfg(test)]
112mod tests;