peace_performance/fruits/
catch_object.rs

1use crate::parse::Pos2;
2
3const PLAYFIELD_WIDTH: f32 = 512.0;
4const BASE_SPEED: f32 = 1.0;
5
6#[derive(Clone)]
7pub struct CatchObject {
8    pub(crate) pos: f32,
9    pub(crate) time: f32,
10
11    pub(crate) hyper_dash: bool,
12    pub(crate) hyper_dist: f32,
13}
14
15impl CatchObject {
16    #[inline]
17    pub(crate) fn new((pos, time): (Pos2, f32)) -> Self {
18        Self {
19            pos: pos.x,
20            time,
21            hyper_dash: false,
22            hyper_dist: 0.0,
23        }
24    }
25
26    pub(crate) fn with_hr(mut self, last_pos: &mut Option<f32>, last_time: &mut f32) -> Self {
27        let mut offset_pos = self.pos;
28        let time_diff = self.time - *last_time;
29
30        if let Some(last_pos_ref) = last_pos.filter(|_| time_diff <= 1000.0) {
31            let pos_diff = offset_pos - last_pos_ref;
32
33            if pos_diff.abs() > f32::EPSILON {
34                if pos_diff.abs() < (time_diff / 3.0).floor() {
35                    if pos_diff > 0.0 {
36                        if offset_pos + pos_diff < PLAYFIELD_WIDTH {
37                            offset_pos += pos_diff;
38                        }
39                    } else if offset_pos + pos_diff > 0.0 {
40                        offset_pos += pos_diff;
41                    }
42                }
43
44                last_pos.replace(offset_pos);
45                *last_time = self.time;
46            }
47
48            self.pos = offset_pos;
49        } else {
50            last_pos.replace(offset_pos);
51            *last_time = self.time;
52        }
53
54        self
55    }
56
57    pub(crate) fn init_hyper_dash(
58        &mut self,
59        half_catcher_width: f32,
60        next: &CatchObject,
61        last_direction: &mut i8,
62        last_excess: &mut f32,
63    ) {
64        let next_x = next.pos;
65        let curr_x = self.pos;
66
67        let this_direction = (next_x > curr_x) as i8 * 2 - 1;
68        let time_to_next = next.time - self.time - 1000.0 / 60.0 / 4.0;
69
70        let sub = if *last_direction == this_direction {
71            *last_excess
72        } else {
73            half_catcher_width
74        };
75
76        let dist_to_next = (next_x - curr_x).abs() - sub;
77        let hyper_dist = time_to_next * BASE_SPEED - dist_to_next;
78
79        if hyper_dist < 0.0 {
80            self.hyper_dash = true;
81            *last_excess = half_catcher_width;
82        } else {
83            self.hyper_dist = hyper_dist;
84            *last_excess = hyper_dist.max(0.0).min(half_catcher_width);
85        }
86
87        *last_direction = this_direction;
88    }
89}