fix sliders

This commit is contained in:
Michael Zhang 2021-01-08 02:18:51 -06:00
parent b1b5050105
commit da967d0c3c
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
2 changed files with 57 additions and 10 deletions

View file

@ -11,7 +11,7 @@ use ggez::{
},
Context, GameError, GameResult,
};
use libosu::{Beatmap, HitObject, HitObjectKind};
use libosu::{Beatmap, HitObject, HitObjectKind, SpinnerInfo};
use crate::audio::{AudioEngine, Sound};
use crate::slider_render::render_slider;
@ -86,7 +86,15 @@ impl Game {
let approach_time = 0.75;
for ho in self.beatmap.hit_objects.iter() {
let ho_time = (ho.start_time.0 as f64) / 1000.0;
if ho_time - approach_time < time && ho_time > time {
let end_time = match ho.kind {
HitObjectKind::Circle => ho_time,
HitObjectKind::Slider(_) => {
let duration = self.beatmap.get_slider_duration(ho).unwrap();
ho_time + duration / 1000.0
}
HitObjectKind::Spinner(SpinnerInfo { end_time }) => (end_time.0 as f64) / 1000.0,
};
if ho_time - approach_time < time && time < end_time {
visible_hitobjects.push(ho);
}
}

View file

@ -2,7 +2,9 @@ use std::collections::VecDeque;
use anyhow::Result;
use ggez::{
graphics::{self, DrawMode, DrawParam, LineCap, LineJoin, Mesh, Rect, StrokeOptions},
graphics::{
self, Color, DrawMode, DrawParam, FillOptions, LineCap, LineJoin, Mesh, Rect, StrokeOptions,
},
nalgebra::Point2,
Context,
};
@ -30,6 +32,16 @@ pub fn render_slider(
let cs_osupx = beatmap.difficulty.circle_size_osupx() as f64;
let cs_real = cs_osupx * osupx_scale_x;
let points_mapped = control_points
.iter()
.map(|point| {
let (x, y) = (point.0 as f64, point.1 as f64);
let x2 = rect.x as f64 + osupx_scale_x * x;
let y2 = rect.y as f64 + osupx_scale_y * y;
[x2 as f32, y2 as f32].into()
})
.collect::<Vec<Point2<_>>>();
let (mut boundx, mut boundy, mut boundw, mut boundh) = (0.0f64, 0.0f64, 0.0f64, 0.0f64);
let spline_mapped = spline
.iter()
@ -50,8 +62,32 @@ pub fn render_slider(
.with_line_cap(LineCap::Round)
.with_line_join(LineJoin::Round)
.with_line_width(cs_real as f32 * 2.0);
let mesh = Mesh::new_polyline(ctx, DrawMode::Stroke(opts), &spline_mapped, graphics::WHITE)?;
graphics::draw(ctx, &mesh, DrawParam::default())?;
let body = Mesh::new_polyline(
ctx,
DrawMode::Stroke(opts),
&spline_mapped,
Color::new(1.0, 1.0, 1.0, 0.5),
)?;
graphics::draw(ctx, &body, DrawParam::default())?;
let frame = Mesh::new_polyline(
ctx,
DrawMode::Stroke(StrokeOptions::default()),
&points_mapped,
graphics::WHITE,
)?;
graphics::draw(ctx, &frame, DrawParam::default())?;
for point in points_mapped {
let size = 5.0;
let rect = Rect::new(point.x - size, point.y - size, size * 2.0, size * 2.0);
let rect = Mesh::new_rectangle(
ctx,
DrawMode::Fill(FillOptions::default()),
rect,
graphics::WHITE,
)?;
graphics::draw(ctx, &rect, DrawParam::default())?;
}
Ok(())
}
@ -84,15 +120,18 @@ fn get_spline(
// find the t-values of the start and end of the slider
let t0 = (center.1 - p1.1).atan2(p1.0 - center.0);
let mut mid = (center.1 - p2.1).atan2(p2.0 - center.0);
let mut t1 = (center.1 - p3.1).atan2(p3.0 - center.0);
// make sure t0 is less than t1
let mut mid = (center.1 - p2.1).atan2(p2.0 - center.0);
while mid < t0 {
mid += 2.0 * std::f64::consts::PI
mid += std::f64::consts::TAU;
}
while t1 < mid {
t1 += 2.0 * std::f64::consts::PI
while t1 < t0 {
t1 += std::f64::consts::TAU;
}
if mid > t1 {
t1 -= std::f64::consts::TAU;
}
// circumference is 2 * pi * r, slider length over circumference is length/(2 * pi * r)