diff --git a/Cargo.lock b/Cargo.lock index 8cb8e70..42ed326 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1072,7 +1072,7 @@ checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" [[package]] name = "libosu" version = "0.0.15" -source = "git+https://github.com/iptq/libosu?rev=7f5e8fd6bdf2798dd40df9595ce630ebc27ac13e#7f5e8fd6bdf2798dd40df9595ce630ebc27ac13e" +source = "git+https://github.com/iptq/libosu?rev=7fbe7afbad55b25398062719ebaccbff0387d139#7fbe7afbad55b25398062719ebaccbff0387d139" dependencies = [ "anyhow", "bitflags", diff --git a/Cargo.toml b/Cargo.toml index f6708d0..ba09c69 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,9 @@ version = "0.1.0" authors = ["Michael Zhang "] edition = "2018" +[profile.release] +debug = true + [workspace] members = [ "bass-sys", @@ -21,4 +24,4 @@ structopt = "0.3.21" [dependencies.libosu] git = "https://github.com/iptq/libosu" -rev = "7f5e8fd6bdf2798dd40df9595ce630ebc27ac13e" +rev = "7fbe7afbad55b25398062719ebaccbff0387d139" diff --git a/src/game/mod.rs b/src/game/mod.rs index 98bc211..a5eba5d 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -19,6 +19,7 @@ use libosu::{ hitobject::{HitObjectKind, SpinnerInfo}, math::Point, spline::Spline, + timing::TimingPointKind, }; use crate::audio::{AudioEngine, Sound}; @@ -26,7 +27,7 @@ use crate::beatmap::{BeatmapExt, STACK_DISTANCE}; use crate::hitobject::HitObjectExt; use crate::skin::Skin; -pub const PLAYFIELD_BOUNDS: Rect = Rect::new(112.0, 112.0, 800.0, 600.0); +pub const PLAYFIELD_BOUNDS: Rect = Rect::new(112.0, 122.0, 800.0, 600.0); pub type SliderCache = HashMap>, Spline>; @@ -274,6 +275,32 @@ impl Game { self.frame += 1; Ok(()) } + + fn seek_by_steps(&self, n: i32) -> Result<()> { + if let Some(song) = &self.song { + let pos = song.position()?; + let mut delta = None; + for timing_point in self.beatmap.inner.timing_points.iter() { + if let TimingPointKind::Uninherited(info) = &timing_point.kind { + if pos > timing_point.time.as_seconds() { + let diff = pos - timing_point.time.as_seconds(); + let tick = info.mpb / 1000.0 / info.meter as f64; + if (diff / tick).abs() < 0.001 { + delta = Some(n as f64 * tick); + } else { + let tick = info.mpb / 1000.0; + delta = Some(n as f64 * tick); + } + break; + } + } + } + if let Some(delta) = delta { + song.set_position(pos + delta)?; + } + } + Ok(()) + } } impl EventHandler for Game { @@ -287,7 +314,20 @@ impl EventHandler for Game { Space => self.toggle_playing(), Colon => {} _ => {} - } + }; + } + + fn key_down_event(&mut self, _: &mut Context, keycode: KeyCode, _: KeyMods, _: bool) { + use KeyCode::*; + match keycode { + Left => { + self.seek_by_steps(-1); + } + Right => { + self.seek_by_steps(1); + } + _ => {} + }; } fn draw(&mut self, ctx: &mut Context) -> GameResult { diff --git a/src/game/seeker.rs b/src/game/seeker.rs index 3235ce8..444664b 100644 --- a/src/game/seeker.rs +++ b/src/game/seeker.rs @@ -1,13 +1,14 @@ use anyhow::Result; use ggez::{ - graphics::{self, DrawParam, Mesh, Rect}, + graphics::{self, Color, DrawParam, Mesh, Rect}, nalgebra::Point2, Context, }; +use libosu::timing::TimingPointKind; use super::Game; -pub const BOUNDS: Rect = Rect::new(46.0, 722.0, 932.0, 36.0); +pub const BOUNDS: Rect = Rect::new(46.0, 732.0, 932.0, 36.0); impl Game { pub(super) fn draw_seeker(&self, ctx: &mut Context) -> Result<()> { @@ -24,7 +25,30 @@ impl Game { graphics::draw(ctx, &line, DrawParam::default())?; if let Some(song) = &self.song { - let percent = song.position()? / song.length()?; + let len = song.length()?; + + for timing_point in self.beatmap.inner.timing_points.iter() { + let color = match timing_point.kind { + TimingPointKind::Inherited(_) => Color::new(0.0, 1.0, 0.0, 0.5), + TimingPointKind::Uninherited(_) => Color::new(1.0, 0.0, 0.0, 0.5), + }; + + let percent = timing_point.time.as_seconds() / len; + let x = BOUNDS.x + percent as f32 * BOUNDS.w; + + let line = Mesh::new_line( + ctx, + &[ + Point2::new(x, BOUNDS.y), + Point2::new(x, BOUNDS.y + BOUNDS.h), + ], + 1.0, + color, + )?; + graphics::draw(ctx, &line, DrawParam::default())?; + } + + let percent = song.position()? / len; let x = BOUNDS.x + percent as f32 * BOUNDS.w; let line = Mesh::new_line( ctx,