Skip to main content

anvilkit_core/time/
timer.rs

1//! # 计时器工具
2//! 
3//! 提供灵活的计时器功能,用于实现延时、周期性事件和时间相关的游戏逻辑。
4//! 
5//! ## 核心概念
6//! 
7//! - **一次性计时器**: 计时结束后停止,适用于延时操作
8//! - **重复计时器**: 计时结束后自动重置,适用于周期性事件
9//! - **暂停/恢复**: 支持计时器的暂停和恢复操作
10//! 
11//! ## 使用场景
12//! 
13//! - 武器冷却时间
14//! - 技能释放间隔
15//! - UI 动画延时
16//! - 周期性事件触发
17//! - 游戏状态切换延时
18
19use std::time::Duration;
20
21/// 计时器状态
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum TimerState {
24    /// 运行中
25    Running,
26    /// 已暂停
27    Paused,
28    /// 已完成(仅对一次性计时器有意义)
29    Finished,
30}
31
32/// 灵活的计时器工具
33/// 
34/// `Timer` 提供了丰富的计时功能,支持一次性和重复计时、暂停恢复等操作。
35/// 它是实现时间相关游戏逻辑的核心工具。
36/// 
37/// ## 设计特点
38/// 
39/// - **零分配**: 所有操作都不涉及内存分配
40/// - **高精度**: 使用 `Duration` 提供微秒级精度
41/// - **状态管理**: 清晰的状态转换和查询接口
42/// - **灵活配置**: 支持多种创建和配置方式
43/// 
44/// ## 示例
45/// 
46/// ```rust
47/// use anvilkit_core::time::Timer;
48/// use std::time::Duration;
49/// 
50/// // 创建 3 秒一次性计时器
51/// let mut timer = Timer::from_seconds(3.0);
52/// 
53/// // 创建 1 秒重复计时器
54/// let mut repeat_timer = Timer::repeating_from_seconds(1.0);
55/// 
56/// // 在游戏循环中更新
57/// let delta = Duration::from_millis(16); // ~60 FPS
58/// 
59/// timer.tick(delta);
60/// repeat_timer.tick(delta);
61/// 
62/// if timer.just_finished() {
63///     println!("Timer finished!");
64/// }
65/// 
66/// if repeat_timer.just_finished() {
67///     println!("Repeat timer triggered!");
68/// }
69/// ```
70#[derive(Debug, Clone)]
71pub struct Timer {
72    /// 计时器总时长
73    duration: Duration,
74    /// 已经过的时间
75    elapsed: Duration,
76    /// 是否为重复计时器
77    repeating: bool,
78    /// 计时器状态
79    state: TimerState,
80    /// 本帧是否刚完成(用于 just_finished 检测)
81    just_finished: bool,
82}
83
84impl Timer {
85    /// 创建新的一次性计时器
86    /// 
87    /// # 参数
88    /// 
89    /// - `duration`: 计时时长
90    /// 
91    /// # 示例
92    /// 
93    /// ```rust
94    /// use anvilkit_core::time::Timer;
95    /// use std::time::Duration;
96    /// 
97    /// let timer = Timer::new(Duration::from_secs(5));
98    /// assert_eq!(timer.duration(), Duration::from_secs(5));
99    /// assert!(!timer.is_repeating());
100    /// ```
101    pub fn new(duration: Duration) -> Self {
102        Self {
103            duration,
104            elapsed: Duration::ZERO,
105            repeating: false,
106            state: TimerState::Running,
107            just_finished: false,
108        }
109    }
110
111    /// 创建新的重复计时器
112    /// 
113    /// # 参数
114    /// 
115    /// - `duration`: 每次计时的时长
116    /// 
117    /// # 示例
118    /// 
119    /// ```rust
120    /// use anvilkit_core::time::Timer;
121    /// use std::time::Duration;
122    /// 
123    /// let timer = Timer::repeating(Duration::from_secs(2));
124    /// assert!(timer.is_repeating());
125    /// ```
126    pub fn repeating(duration: Duration) -> Self {
127        Self {
128            duration,
129            elapsed: Duration::ZERO,
130            repeating: true,
131            state: TimerState::Running,
132            just_finished: false,
133        }
134    }
135
136    /// 从秒数创建一次性计时器
137    /// 
138    /// # 示例
139    /// 
140    /// ```rust
141    /// use anvilkit_core::time::Timer;
142    /// 
143    /// let timer = Timer::from_seconds(3.5);
144    /// assert_eq!(timer.duration_seconds(), 3.5);
145    /// ```
146    pub fn from_seconds(seconds: f32) -> Self {
147        Self::new(Duration::from_secs_f32(seconds))
148    }
149
150    /// 从秒数创建重复计时器
151    /// 
152    /// # 示例
153    /// 
154    /// ```rust
155    /// use anvilkit_core::time::Timer;
156    /// 
157    /// let timer = Timer::repeating_from_seconds(1.0);
158    /// assert!(timer.is_repeating());
159    /// assert_eq!(timer.duration_seconds(), 1.0);
160    /// ```
161    pub fn repeating_from_seconds(seconds: f32) -> Self {
162        Self::repeating(Duration::from_secs_f32(seconds))
163    }
164
165    /// 从毫秒数创建一次性计时器
166    pub fn from_millis(millis: u64) -> Self {
167        Self::new(Duration::from_millis(millis))
168    }
169
170    /// 从毫秒数创建重复计时器
171    pub fn repeating_from_millis(millis: u64) -> Self {
172        Self::repeating(Duration::from_millis(millis))
173    }
174
175    /// 更新计时器
176    /// 
177    /// 应该在每帧调用此方法来推进计时器。
178    /// 
179    /// # 参数
180    /// 
181    /// - `delta`: 自上次更新以来的时间间隔
182    /// 
183    /// # 示例
184    /// 
185    /// ```rust
186    /// use anvilkit_core::time::Timer;
187    /// use std::time::Duration;
188    /// 
189    /// let mut timer = Timer::from_seconds(1.0);
190    /// 
191    /// // 模拟 0.5 秒
192    /// timer.tick(Duration::from_millis(500));
193    /// assert_eq!(timer.percent(), 0.5);
194    /// assert!(!timer.finished());
195    /// 
196    /// // 再模拟 0.5 秒
197    /// timer.tick(Duration::from_millis(500));
198    /// assert!(timer.finished());
199    /// assert!(timer.just_finished());
200    /// ```
201    pub fn tick(&mut self, delta: Duration) {
202        self.just_finished = false;
203
204        if self.state != TimerState::Running {
205            return;
206        }
207
208        let _old_elapsed = self.elapsed;
209        self.elapsed += delta;
210
211        // 检查是否完成
212        if self.elapsed >= self.duration {
213            self.just_finished = true;
214
215            if self.repeating {
216                // 重复计时器:重置并保留超出的时间
217                let overflow = self.elapsed - self.duration;
218                self.elapsed = overflow;
219                
220                // 如果超出时间仍然大于等于持续时间,继续处理
221                // 这处理了 delta 时间非常大的情况
222                while self.elapsed >= self.duration {
223                    self.elapsed -= self.duration;
224                }
225            } else {
226                // 一次性计时器:标记为完成
227                self.elapsed = self.duration;
228                self.state = TimerState::Finished;
229            }
230        }
231    }
232
233    /// 检查计时器是否已完成
234    /// 
235    /// 对于一次性计时器,完成后会一直返回 `true`。
236    /// 对于重复计时器,只有在刚完成的那一帧返回 `true`。
237    /// 
238    /// # 示例
239    /// 
240    /// ```rust
241    /// use anvilkit_core::time::Timer;
242    /// use std::time::Duration;
243    /// 
244    /// let mut timer = Timer::from_seconds(1.0);
245    /// assert!(!timer.finished());
246    /// 
247    /// timer.tick(Duration::from_secs(1));
248    /// assert!(timer.finished());
249    /// ```
250    pub fn finished(&self) -> bool {
251        match self.state {
252            TimerState::Finished => true,
253            _ => self.repeating && self.just_finished,
254        }
255    }
256
257    /// 检查计时器是否在本帧刚完成
258    /// 
259    /// 这对于触发一次性事件非常有用,避免重复触发。
260    /// 
261    /// # 示例
262    /// 
263    /// ```rust
264    /// use anvilkit_core::time::Timer;
265    /// use std::time::Duration;
266    /// 
267    /// let mut timer = Timer::from_seconds(1.0);
268    /// 
269    /// timer.tick(Duration::from_millis(999));
270    /// assert!(!timer.just_finished());
271    /// 
272    /// timer.tick(Duration::from_millis(1));
273    /// assert!(timer.just_finished());
274    /// 
275    /// timer.tick(Duration::from_millis(1));
276    /// assert!(!timer.just_finished()); // 下一帧不再是 "刚完成"
277    /// ```
278    pub fn just_finished(&self) -> bool {
279        self.just_finished
280    }
281
282    /// 获取已经过的时间
283    pub fn elapsed(&self) -> Duration {
284        self.elapsed
285    }
286
287    /// 获取已经过的时间(秒)
288    pub fn elapsed_seconds(&self) -> f32 {
289        self.elapsed.as_secs_f32()
290    }
291
292    /// 获取计时器总时长
293    pub fn duration(&self) -> Duration {
294        self.duration
295    }
296
297    /// 获取计时器总时长(秒)
298    pub fn duration_seconds(&self) -> f32 {
299        self.duration.as_secs_f32()
300    }
301
302    /// 获取完成百分比 (0.0 到 1.0)
303    /// 
304    /// # 示例
305    /// 
306    /// ```rust
307    /// use anvilkit_core::time::Timer;
308    /// use std::time::Duration;
309    /// 
310    /// let mut timer = Timer::from_seconds(2.0);
311    /// timer.tick(Duration::from_secs(1));
312    /// 
313    /// assert_eq!(timer.percent(), 0.5);
314    /// ```
315    pub fn percent(&self) -> f32 {
316        if self.duration.is_zero() {
317            1.0
318        } else {
319            (self.elapsed.as_secs_f32() / self.duration.as_secs_f32()).min(1.0)
320        }
321    }
322
323    /// 获取剩余时间
324    /// 
325    /// # 示例
326    /// 
327    /// ```rust
328    /// use anvilkit_core::time::Timer;
329    /// use std::time::Duration;
330    /// 
331    /// let mut timer = Timer::from_seconds(3.0);
332    /// timer.tick(Duration::from_secs(1));
333    /// 
334    /// assert_eq!(timer.remaining(), Duration::from_secs(2));
335    /// ```
336    pub fn remaining(&self) -> Duration {
337        self.duration.saturating_sub(self.elapsed)
338    }
339
340    /// 获取剩余时间(秒)
341    pub fn remaining_seconds(&self) -> f32 {
342        self.remaining().as_secs_f32()
343    }
344
345    /// 重置计时器到初始状态
346    /// 
347    /// # 示例
348    /// 
349    /// ```rust
350    /// use anvilkit_core::time::Timer;
351    /// use std::time::Duration;
352    /// 
353    /// let mut timer = Timer::from_seconds(1.0);
354    /// timer.tick(Duration::from_millis(500));
355    /// 
356    /// assert_eq!(timer.percent(), 0.5);
357    /// 
358    /// timer.reset();
359    /// assert_eq!(timer.percent(), 0.0);
360    /// assert!(!timer.finished());
361    /// ```
362    pub fn reset(&mut self) {
363        self.elapsed = Duration::ZERO;
364        self.state = TimerState::Running;
365        self.just_finished = false;
366    }
367
368    /// 暂停计时器
369    /// 
370    /// # 示例
371    /// 
372    /// ```rust
373    /// use anvilkit_core::time::Timer;
374    /// use std::time::Duration;
375    /// 
376    /// let mut timer = Timer::from_seconds(1.0);
377    /// timer.pause();
378    /// 
379    /// assert!(timer.is_paused());
380    /// 
381    /// // 暂停状态下 tick 不会推进时间
382    /// timer.tick(Duration::from_secs(1));
383    /// assert_eq!(timer.elapsed_seconds(), 0.0);
384    /// ```
385    pub fn pause(&mut self) {
386        if self.state == TimerState::Running {
387            self.state = TimerState::Paused;
388        }
389    }
390
391    /// 恢复计时器
392    /// 
393    /// # 示例
394    /// 
395    /// ```rust
396    /// use anvilkit_core::time::Timer;
397    /// use std::time::Duration;
398    /// 
399    /// let mut timer = Timer::from_seconds(1.0);
400    /// timer.pause();
401    /// timer.resume();
402    /// 
403    /// assert!(timer.is_running());
404    /// ```
405    pub fn resume(&mut self) {
406        if self.state == TimerState::Paused {
407            self.state = TimerState::Running;
408        }
409    }
410
411    /// 设置计时器时长
412    /// 
413    /// # 注意
414    /// 
415    /// 如果新时长小于已经过的时间,计时器会立即完成。
416    /// 
417    /// # 示例
418    /// 
419    /// ```rust
420    /// use anvilkit_core::time::Timer;
421    /// use std::time::Duration;
422    /// 
423    /// let mut timer = Timer::from_seconds(1.0);
424    /// timer.set_duration(Duration::from_secs(2));
425    /// 
426    /// assert_eq!(timer.duration_seconds(), 2.0);
427    /// ```
428    pub fn set_duration(&mut self, duration: Duration) {
429        self.duration = duration;
430        
431        // 如果新时长小于已经过的时间,立即完成
432        if self.elapsed >= self.duration {
433            if self.repeating {
434                self.elapsed = Duration::ZERO;
435                self.just_finished = true;
436            } else {
437                self.elapsed = self.duration;
438                self.state = TimerState::Finished;
439                self.just_finished = true;
440            }
441        }
442    }
443
444    /// 设置是否为重复计时器
445    /// 
446    /// # 示例
447    /// 
448    /// ```rust
449    /// use anvilkit_core::time::Timer;
450    /// 
451    /// let mut timer = Timer::from_seconds(1.0);
452    /// assert!(!timer.is_repeating());
453    /// 
454    /// timer.set_repeating(true);
455    /// assert!(timer.is_repeating());
456    /// ```
457    pub fn set_repeating(&mut self, repeating: bool) {
458        self.repeating = repeating;
459
460        if repeating {
461            // 如果设置为重复模式且当前已完成,则重置定时器
462            if self.state == TimerState::Finished {
463                self.elapsed = Duration::ZERO;
464                self.state = TimerState::Running;
465            }
466        } else {
467            // 如果从重复改为非重复,且已完成,则标记为完成状态
468            if self.elapsed >= self.duration {
469                self.state = TimerState::Finished;
470            }
471        }
472    }
473
474    /// 检查是否为重复计时器
475    pub fn is_repeating(&self) -> bool {
476        self.repeating
477    }
478
479    /// 检查计时器是否正在运行
480    pub fn is_running(&self) -> bool {
481        self.state == TimerState::Running
482    }
483
484    /// 检查计时器是否已暂停
485    pub fn is_paused(&self) -> bool {
486        self.state == TimerState::Paused
487    }
488
489    /// 获取计时器状态
490    pub fn state(&self) -> TimerState {
491        self.state
492    }
493
494    /// 强制完成计时器
495    /// 
496    /// 将已经过时间设置为总时长,并触发完成状态。
497    /// 
498    /// # 示例
499    /// 
500    /// ```rust
501    /// use anvilkit_core::time::Timer;
502    /// 
503    /// let mut timer = Timer::from_seconds(10.0);
504    /// timer.finish();
505    /// 
506    /// assert!(timer.finished());
507    /// assert!(timer.just_finished());
508    /// ```
509    pub fn finish(&mut self) {
510        self.elapsed = self.duration;
511        self.just_finished = true;
512        
513        if !self.repeating {
514            self.state = TimerState::Finished;
515        }
516    }
517}
518
519#[cfg(test)]
520mod tests {
521    use super::*;
522    use std::time::Duration;
523    use approx::assert_relative_eq;
524
525    #[test]
526    fn test_timer_creation() {
527        let timer = Timer::from_seconds(2.0);
528        assert_eq!(timer.duration_seconds(), 2.0);
529        assert!(!timer.is_repeating());
530        assert!(timer.is_running());
531        assert!(!timer.finished());
532    }
533
534    #[test]
535    fn test_repeating_timer_creation() {
536        let timer = Timer::repeating_from_seconds(1.5);
537        assert_eq!(timer.duration_seconds(), 1.5);
538        assert!(timer.is_repeating());
539        assert!(timer.is_running());
540    }
541
542    #[test]
543    fn test_timer_tick() {
544        let mut timer = Timer::from_seconds(1.0);
545        
546        // 半程
547        timer.tick(Duration::from_millis(500));
548        assert_eq!(timer.percent(), 0.5);
549        assert!(!timer.finished());
550        assert!(!timer.just_finished());
551        
552        // 完成
553        timer.tick(Duration::from_millis(500));
554        assert!(timer.finished());
555        assert!(timer.just_finished());
556        assert_eq!(timer.percent(), 1.0);
557        
558        // 下一帧
559        timer.tick(Duration::from_millis(1));
560        assert!(timer.finished());
561        assert!(!timer.just_finished()); // 不再是 "刚完成"
562    }
563
564    #[test]
565    fn test_repeating_timer() {
566        let mut timer = Timer::repeating_from_seconds(1.0);
567        
568        // 第一次完成
569        timer.tick(Duration::from_secs(1));
570        assert!(timer.finished());
571        assert!(timer.just_finished());
572        
573        // 下一帧,应该重置
574        timer.tick(Duration::from_millis(1));
575        assert!(!timer.finished());
576        assert!(!timer.just_finished());
577        assert!(timer.elapsed_seconds() < 0.1);
578    }
579
580    #[test]
581    fn test_timer_overflow() {
582        let mut timer = Timer::repeating_from_seconds(1.0);
583        
584        // 一次性跳过多个周期
585        timer.tick(Duration::from_millis(2500)); // 2.5 秒
586        
587        assert!(timer.just_finished());
588        assert_relative_eq!(timer.elapsed_seconds(), 0.5, epsilon = 1e-3);
589    }
590
591    #[test]
592    fn test_timer_pause_resume() {
593        let mut timer = Timer::from_seconds(1.0);
594        
595        timer.tick(Duration::from_millis(300));
596        assert_eq!(timer.percent(), 0.3);
597        
598        timer.pause();
599        assert!(timer.is_paused());
600        
601        // 暂停状态下不应该推进
602        timer.tick(Duration::from_millis(500));
603        assert_eq!(timer.percent(), 0.3);
604        
605        timer.resume();
606        assert!(timer.is_running());
607        
608        timer.tick(Duration::from_millis(700));
609        assert!(timer.finished());
610    }
611
612    #[test]
613    fn test_timer_reset() {
614        let mut timer = Timer::from_seconds(1.0);
615        timer.tick(Duration::from_millis(800));
616        
617        assert_eq!(timer.percent(), 0.8);
618        
619        timer.reset();
620        assert_eq!(timer.percent(), 0.0);
621        assert!(!timer.finished());
622        assert!(timer.is_running());
623    }
624
625    #[test]
626    fn test_timer_set_duration() {
627        let mut timer = Timer::from_seconds(2.0);
628        timer.tick(Duration::from_secs(1));
629        
630        // 延长时间
631        timer.set_duration(Duration::from_secs(3));
632        assert_eq!(timer.percent(), 1.0 / 3.0);
633        
634        // 缩短时间到已经过的时间以下
635        timer.set_duration(Duration::from_millis(500));
636        assert!(timer.finished());
637        assert!(timer.just_finished());
638    }
639
640    #[test]
641    fn test_timer_remaining() {
642        let mut timer = Timer::from_seconds(5.0);
643        timer.tick(Duration::from_secs(2));
644        
645        assert_eq!(timer.remaining(), Duration::from_secs(3));
646        assert_eq!(timer.remaining_seconds(), 3.0);
647    }
648
649    #[test]
650    fn test_timer_finish() {
651        let mut timer = Timer::from_seconds(10.0);
652        timer.finish();
653        
654        assert!(timer.finished());
655        assert!(timer.just_finished());
656        assert_eq!(timer.percent(), 1.0);
657    }
658
659    #[test]
660    fn test_timer_state_transitions() {
661        let mut timer = Timer::from_seconds(1.0);
662        
663        assert_eq!(timer.state(), TimerState::Running);
664        
665        timer.pause();
666        assert_eq!(timer.state(), TimerState::Paused);
667        
668        timer.resume();
669        assert_eq!(timer.state(), TimerState::Running);
670        
671        timer.tick(Duration::from_secs(1));
672        assert_eq!(timer.state(), TimerState::Finished);
673    }
674
675    #[test]
676    fn test_zero_duration_timer() {
677        let mut timer = Timer::new(Duration::ZERO);
678        assert_eq!(timer.percent(), 1.0);
679        
680        timer.tick(Duration::from_millis(1));
681        assert!(timer.finished());
682        assert!(timer.just_finished());
683    }
684
685    #[test]
686    fn test_timer_set_repeating() {
687        let mut timer = Timer::from_seconds(1.0);
688        timer.tick(Duration::from_secs(1));
689
690        assert!(timer.finished());
691
692        // 改为重复计时器
693        timer.set_repeating(true);
694        timer.tick(Duration::from_millis(1));
695
696        // 应该重置并继续运行
697        assert!(!timer.finished());
698        assert!(timer.elapsed_seconds() < 0.1);
699    }
700
701    #[test]
702    fn test_timer_from_millis() {
703        let timer = Timer::from_millis(500);
704        assert_eq!(timer.duration(), Duration::from_millis(500));
705        assert!(!timer.is_repeating());
706    }
707
708    #[test]
709    fn test_timer_repeating_from_millis() {
710        let timer = Timer::repeating_from_millis(250);
711        assert_eq!(timer.duration(), Duration::from_millis(250));
712        assert!(timer.is_repeating());
713    }
714
715    #[test]
716    fn test_timer_pause_prevents_finish() {
717        let mut timer = Timer::from_seconds(1.0);
718        timer.tick(Duration::from_millis(500));
719        timer.pause();
720        timer.tick(Duration::from_secs(10));
721
722        // 暂停期间不应完成
723        assert!(!timer.finished());
724        assert_relative_eq!(timer.percent(), 0.5, epsilon = 1e-3);
725    }
726
727    #[test]
728    fn test_timer_resume_finished_timer() {
729        let mut timer = Timer::from_seconds(1.0);
730        timer.tick(Duration::from_secs(1));
731        assert!(timer.finished());
732
733        // 对已完成的计时器调用 resume 不应有效果
734        timer.resume();
735        assert!(timer.finished());
736    }
737
738    #[test]
739    fn test_timer_pause_already_paused() {
740        let mut timer = Timer::from_seconds(1.0);
741        timer.pause();
742        timer.pause(); // 重复暂停应该是幂等的
743        assert!(timer.is_paused());
744    }
745
746    #[test]
747    fn test_timer_resume_when_running() {
748        let mut timer = Timer::from_seconds(1.0);
749        timer.resume(); // 运行时调用 resume 应该是幂等的
750        assert!(timer.is_running());
751    }
752
753    #[test]
754    fn test_timer_elapsed_seconds() {
755        let mut timer = Timer::from_seconds(2.0);
756        timer.tick(Duration::from_millis(750));
757        assert_relative_eq!(timer.elapsed_seconds(), 0.75, epsilon = 1e-3);
758    }
759
760    #[test]
761    fn test_timer_remaining_after_finish() {
762        let mut timer = Timer::from_seconds(1.0);
763        timer.tick(Duration::from_secs(2));
764        assert_eq!(timer.remaining(), Duration::ZERO);
765    }
766
767    #[test]
768    fn test_repeating_timer_rapid_ticks() {
769        let mut timer = Timer::repeating(Duration::from_millis(100));
770
771        // 多次小 tick
772        for _ in 0..20 {
773            timer.tick(Duration::from_millis(10));
774        }
775
776        // After 200ms with 100ms period, timer should have wrapped around
777        assert!(timer.elapsed_seconds() < 0.1);
778    }
779
780    #[test]
781    fn test_timer_set_duration_while_running() {
782        let mut timer = Timer::from_seconds(5.0);
783        timer.tick(Duration::from_secs(2));
784
785        // 延长 duration
786        timer.set_duration(Duration::from_secs(10));
787        assert!(!timer.finished());
788        assert_relative_eq!(timer.percent(), 0.2, epsilon = 1e-3);
789    }
790
791    #[test]
792    fn test_timer_finish_repeating() {
793        let mut timer = Timer::repeating_from_seconds(1.0);
794        timer.finish();
795
796        assert!(timer.just_finished());
797        // 重复计时器 finish 后不应进入 Finished 状态
798        assert_eq!(timer.state(), TimerState::Running);
799    }
800}