minor cleanup for osu_fast

This commit is contained in:
MaxOhn
2021-11-09 05:22:44 +01:00
parent a01cd1f2a3
commit ab267fd648
2 changed files with 124 additions and 148 deletions
+23 -85
View File
@@ -7,6 +7,8 @@
use std::mem; use std::mem;
use self::osu_object::ObjectParameters;
use super::DifficultyAttributes; use super::DifficultyAttributes;
mod difficulty_object; mod difficulty_object;
@@ -21,7 +23,7 @@ use skill::Skill;
use skill_kind::SkillKind; use skill_kind::SkillKind;
use slider_state::SliderState; use slider_state::SliderState;
use crate::{parse::HitObjectKind, Beatmap, Mods, Strains}; use crate::{Beatmap, Mods, Strains};
const OBJECT_RADIUS: f32 = 64.0; const OBJECT_RADIUS: f32 = 64.0;
const SECTION_LEN: f32 = 400.0; const SECTION_LEN: f32 = 400.0;
@@ -63,62 +65,19 @@ pub fn stars(
scaling_factor *= 1.0 + small_circle_bonus; scaling_factor *= 1.0 + small_circle_bonus;
} }
let clock_rate = attributes.clock_rate; let mut params = ObjectParameters {
map,
let mut max_combo = 0; radius,
let mut state = SliderState::new(map); clock_rate: attributes.clock_rate,
max_combo: 0,
slider_state: SliderState::new(map),
};
let mut hit_objects = map let mut hit_objects = map
.hit_objects .hit_objects
.iter() .iter()
.take(take) .take(take)
.filter_map(|h| match &h.kind { .filter_map(|h| OsuObject::new(h, &mut params));
HitObjectKind::Circle => {
max_combo += 1;
Some(OsuObject::circle(h, clock_rate))
}
#[cfg(feature = "sliders")]
HitObjectKind::Slider {
pixel_len,
repeats,
control_points,
} => {
max_combo += state.count_ticks(h.start_time, *pixel_len, *repeats, map);
Some(OsuObject::slider(
h,
clock_rate,
radius,
*repeats,
*pixel_len,
control_points,
))
}
#[cfg(not(feature = "sliders"))]
HitObjectKind::Slider {
pixel_len,
span_count,
last_control_point,
} => {
max_combo += state.count_ticks(h.start_time, *pixel_len, *span_count, map);
Some(OsuObject::slider(
h,
clock_rate,
radius,
*span_count,
*pixel_len,
*last_control_point,
))
}
HitObjectKind::Spinner { .. } => {
max_combo += 1;
Some(OsuObject::spinner(h, clock_rate))
}
HitObjectKind::Hold { .. } => None,
});
let fl = mods.fl(); let fl = mods.fl();
let mut skills = Vec::with_capacity(2 + fl as usize); let mut skills = Vec::with_capacity(2 + fl as usize);
@@ -234,7 +193,7 @@ pub fn stars(
speed_strain: speed_rating, speed_strain: speed_rating,
aim_strain: aim_rating, aim_strain: aim_rating,
flashlight_rating, flashlight_rating,
max_combo, max_combo: params.max_combo,
n_circles: map.n_circles as usize, n_circles: map.n_circles as usize,
n_spinners: map.n_spinners as usize, n_spinners: map.n_spinners as usize,
n_sliders: map.n_sliders as usize, n_sliders: map.n_sliders as usize,
@@ -261,39 +220,18 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
scaling_factor *= 1.0 + small_circle_bonus; scaling_factor *= 1.0 + small_circle_bonus;
} }
let clock_rate = attributes.clock_rate; let mut params = ObjectParameters {
map,
radius,
clock_rate: attributes.clock_rate,
max_combo: 0,
slider_state: SliderState::new(map),
};
let mut hit_objects = map.hit_objects.iter().filter_map(|h| match &h.kind { let mut hit_objects = map
HitObjectKind::Circle => Some(OsuObject::circle(h, clock_rate)), .hit_objects
#[cfg(feature = "sliders")] .iter()
HitObjectKind::Slider { .filter_map(|h| OsuObject::new(h, &mut params));
repeats,
control_points,
pixel_len,
} => Some(OsuObject::slider(
h,
clock_rate,
radius,
*repeats,
*pixel_len,
control_points,
)),
#[cfg(not(feature = "sliders"))]
HitObjectKind::Slider {
span_count,
last_control_point,
pixel_len,
} => Some(OsuObject::slider(
h,
clock_rate,
radius,
*span_count,
*pixel_len,
*last_control_point,
)),
HitObjectKind::Spinner { .. } => Some(OsuObject::spinner(h, clock_rate)),
HitObjectKind::Hold { .. } => None,
});
let fl = mods.fl(); let fl = mods.fl();
let mut skills = Vec::with_capacity(2 + fl as usize); let mut skills = Vec::with_capacity(2 + fl as usize);
+78 -40
View File
@@ -1,4 +1,9 @@
use crate::parse::{HitObject, Pos2}; use crate::{
parse::{HitObject, HitObjectKind, Pos2},
Beatmap,
};
use super::slider_state::SliderState;
pub(crate) struct OsuObject { pub(crate) struct OsuObject {
pub(crate) pos: Pos2, pub(crate) pos: Pos2,
@@ -12,91 +17,124 @@ pub(crate) enum OsuObjectKind {
Spinner, Spinner,
} }
impl OsuObject { pub(crate) struct ObjectParameters<'a> {
pub(crate) fn circle(h: &HitObject, clock_rate: f32) -> Self { pub(crate) map: &'a Beatmap,
Self { pub(crate) radius: f32,
pos: h.pos, pub(crate) clock_rate: f32,
time: h.start_time / clock_rate, pub(crate) max_combo: usize,
kind: OsuObjectKind::Circle, pub(crate) slider_state: SliderState<'a>,
}
} }
impl OsuObject {
pub(crate) fn new(h: &HitObject, params: &mut ObjectParameters<'_>) -> Option<Self> {
let time = h.start_time / params.clock_rate;
let obj = match &h.kind {
HitObjectKind::Circle => {
params.max_combo += 1;
Self::circle(h.pos, time)
}
#[cfg(feature = "sliders")] #[cfg(feature = "sliders")]
pub(crate) fn slider( HitObjectKind::Slider {
h: &HitObject, pixel_len,
clock_rate: f32, repeats,
radius: f32, control_points,
repeats: usize, } => {
pixel_len: f32, let span_count = *repeats + 1;
control_points: &[crate::parse::PathControlPoint],
) -> Self { params.max_combo += params.slider_state.count_ticks(
h.start_time,
*pixel_len,
span_count,
params.map,
);
match control_points.last() { match control_points.last() {
Some(point) => { Some(point) => {
let follow_circle_radius = radius * 3.0; let follow_circle_radius = params.radius * 3.0;
let span_count = (repeats + 1) as f32;
let travel_dist = let travel_dist = Self::approximate_travel_dist(
Self::approximate_travel_dist(follow_circle_radius, span_count, point.pos); follow_circle_radius,
span_count as f32,
point.pos,
);
let mut end_pos = h.pos; let mut end_pos = h.pos;
if repeats % 2 == 0 && pixel_len > follow_circle_radius { if repeats % 2 == 0 && *pixel_len > follow_circle_radius {
end_pos += point.pos end_pos += point.pos
} }
Self { Self {
pos: h.pos, pos: h.pos,
time: h.start_time / clock_rate, time,
kind: OsuObjectKind::Slider { kind: OsuObjectKind::Slider {
end_pos, end_pos,
travel_dist, travel_dist,
}, },
} }
} }
None => Self::circle(h, clock_rate), None => Self::circle(h.pos, time),
} }
} }
#[cfg(not(feature = "sliders"))] #[cfg(not(feature = "sliders"))]
pub(crate) fn slider( HitObjectKind::Slider {
h: &HitObject, pixel_len,
clock_rate: f32, span_count,
radius: f32, last_control_point,
span_count: usize, } => {
pixel_len: f32, params.max_combo += params.slider_state.count_ticks(
last_control_point: Pos2, h.start_time,
) -> Self { *pixel_len,
let follow_circle_radius = radius * 3.0; *span_count,
params.map,
);
let follow_circle_radius = params.radius * 3.0;
let travel_dist = Self::approximate_travel_dist( let travel_dist = Self::approximate_travel_dist(
follow_circle_radius, follow_circle_radius,
span_count as f32, *span_count as f32,
point.pos - h.pos, *last_control_point - h.pos,
); );
let end_pos = if span_count % 2 == 1 && pixel_len > follow_circle_radius { let end_pos = if span_count % 2 == 1 && *pixel_len > follow_circle_radius {
last_control_point *last_control_point
} else { } else {
h.pos h.pos
}; };
Self { Self {
pos: h.pos, pos: h.pos,
time: h.start_time / clock_rate, time,
kind: OsuObjectKind::Slider { kind: OsuObjectKind::Slider {
end_pos, end_pos,
travel_dist, travel_dist,
}, },
} }
} }
HitObjectKind::Spinner { .. } => {
params.max_combo += 1;
pub(crate) fn spinner(h: &HitObject, clock_rate: f32) -> Self {
Self { Self {
pos: h.pos, pos: h.pos,
time: h.start_time / clock_rate, time,
kind: OsuObjectKind::Spinner, kind: OsuObjectKind::Spinner,
} }
} }
HitObjectKind::Hold { .. } => return None,
};
Some(obj)
}
fn circle(pos: Pos2, time: f32) -> Self {
Self {
pos,
time,
kind: OsuObjectKind::Circle,
}
}
pub(crate) fn is_slider(&self) -> bool { pub(crate) fn is_slider(&self) -> bool {
matches!(self.kind, OsuObjectKind::Slider { .. }) matches!(self.kind, OsuObjectKind::Slider { .. })