notch hell

This commit is contained in:
Michael Zhang 2021-01-08 02:41:33 -06:00
parent 7914d2bafb
commit e0875cd09e
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
6 changed files with 66 additions and 31 deletions

2
Cargo.lock generated
View file

@ -1132,7 +1132,7 @@ checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"
[[package]] [[package]]
name = "libosu" name = "libosu"
version = "0.0.12" version = "0.0.12"
source = "git+https://github.com/iptq/libosu?rev=5a8501aec0f4f2232507f80a65b8b31be8756414#5a8501aec0f4f2232507f80a65b8b31be8756414" source = "git+https://github.com/iptq/libosu?rev=95a87c57e1075ffab473124d9564233028e79423#95a87c57e1075ffab473124d9564233028e79423"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bitflags", "bitflags",

View file

@ -19,4 +19,4 @@ num = "0.3.1"
[dependencies.libosu] [dependencies.libosu]
git = "https://github.com/iptq/libosu" git = "https://github.com/iptq/libosu"
rev = "5a8501aec0f4f2232507f80a65b8b31be8756414" rev = "95a87c57e1075ffab473124d9564233028e79423"

View file

@ -17,7 +17,9 @@ extern_log! {
pub fn BASS_ChannelPause(handle: DWORD) -> BOOL; pub fn BASS_ChannelPause(handle: DWORD) -> BOOL;
pub fn BASS_ChannelGetLength(handle: DWORD, mode: DWORD) -> QWORD; pub fn BASS_ChannelGetLength(handle: DWORD, mode: DWORD) -> QWORD;
pub fn BASS_ChannelGetPosition(handle: DWORD, mode: DWORD) -> QWORD; pub fn BASS_ChannelGetPosition(handle: DWORD, mode: DWORD) -> QWORD;
pub fn BASS_ChannelSetPosition(handle: DWORD, pos: QWORD, mode: DWORD);
pub fn BASS_ChannelBytes2Seconds(handle: DWORD, pos: QWORD) -> f64; pub fn BASS_ChannelBytes2Seconds(handle: DWORD, pos: QWORD) -> f64;
pub fn BASS_ChannelSeconds2Bytes(handle: DWORD, pos: f64) -> QWORD;
pub fn BASS_GetDevice() -> DWORD; pub fn BASS_GetDevice() -> DWORD;
pub fn BASS_GetDeviceInfo(device: DWORD, info: *mut BASS_DEVICEINFO) -> BOOL; pub fn BASS_GetDeviceInfo(device: DWORD, info: *mut BASS_DEVICEINFO) -> BOOL;

View file

@ -76,4 +76,12 @@ impl Sound {
}; };
Ok(time) Ok(time)
} }
pub fn set_position(&self, pos: f64) -> Result<()> {
unsafe {
let pos_bytes = bass::BASS_ChannelSeconds2Bytes(self.handle, pos);
bass::BASS_ChannelSetPosition(self.handle, pos_bytes, BASS_POS_BYTE);
}
Ok(())
}
} }

View file

@ -48,7 +48,10 @@ impl Game {
self.beatmap = Beatmap::from_osz(&contents)?; self.beatmap = Beatmap::from_osz(&contents)?;
let dir = path.parent().unwrap(); let dir = path.parent().unwrap();
self.song = Sound::create(dir.join(&self.beatmap.audio_filename)).map(Some)?;
let song = Sound::create(dir.join(&self.beatmap.audio_filename))?;
song.set_position(113.0)?;
self.song = Some(song);
Ok(()) Ok(())
} }
@ -82,20 +85,40 @@ impl Game {
graphics::queue_text(ctx, &text, [0.0, 0.0], Some(WHITE)); graphics::queue_text(ctx, &text, [0.0, 0.0], Some(WHITE));
graphics::draw_queued_text(ctx, DrawParam::default(), None, FilterMode::Linear)?; graphics::draw_queued_text(ctx, DrawParam::default(), None, FilterMode::Linear)?;
struct DrawInfo<'a> {
hit_object: &'a HitObject,
opacity: f64,
end_time: f64,
}
let mut visible_hitobjects = Vec::new(); let mut visible_hitobjects = Vec::new();
let approach_time = 0.75; let preempt = (self.beatmap.difficulty.approach_preempt() as f64) / 1000.0;
let fade_in = (self.beatmap.difficulty.approach_fade_time() as f64) / 1000.0;
for ho in self.beatmap.hit_objects.iter() { for ho in self.beatmap.hit_objects.iter() {
let ho_time = (ho.start_time.0 as f64) / 1000.0; let ho_time = (ho.start_time.0 as f64) / 1000.0;
let end_time = match ho.kind { let end_time;
HitObjectKind::Circle => ho_time, let opacity = if time > ho_time - fade_in {
1.0
} else {
// TODO: calculate ease
(time - (ho_time - preempt)) / fade_in
};
match ho.kind {
HitObjectKind::Circle => end_time = ho_time,
HitObjectKind::Slider(_) => { HitObjectKind::Slider(_) => {
let duration = self.beatmap.get_slider_duration(ho).unwrap(); let duration = self.beatmap.get_slider_duration(ho).unwrap();
ho_time + duration / 1000.0 end_time = ho_time + duration / 1000.0;
} }
HitObjectKind::Spinner(SpinnerInfo { end_time }) => (end_time.0 as f64) / 1000.0, HitObjectKind::Spinner(SpinnerInfo {
end_time: spinner_end,
}) => end_time = (spinner_end.0 as f64) / 1000.0,
}; };
if ho_time - approach_time < time && time < end_time { if ho_time - preempt < time && time < end_time {
visible_hitobjects.push(ho); visible_hitobjects.push(DrawInfo {
hit_object: ho,
opacity,
end_time,
});
} }
} }
@ -104,15 +127,18 @@ impl Game {
let cs_osupx = self.beatmap.difficulty.circle_size_osupx(); let cs_osupx = self.beatmap.difficulty.circle_size_osupx();
let cs_real = cs_osupx * osupx_scale_x; let cs_real = cs_osupx * osupx_scale_x;
for ho in visible_hitobjects.iter() { for draw_info in visible_hitobjects.iter() {
let ho = draw_info.hit_object;
let ho_time = (ho.start_time.0 as f64) / 1000.0; let ho_time = (ho.start_time.0 as f64) / 1000.0;
let pos = [ let pos = [
EDITOR_SCREEN.x + osupx_scale_x * ho.pos.0 as f32, EDITOR_SCREEN.x + osupx_scale_x * ho.pos.0 as f32,
EDITOR_SCREEN.y + osupx_scale_y * ho.pos.1 as f32, EDITOR_SCREEN.y + osupx_scale_y * ho.pos.1 as f32,
]; ];
let color = graphics::Color::new(1.0, 1.0, 1.0, draw_info.opacity as f32);
if let HitObjectKind::Slider(_) = ho.kind { if let HitObjectKind::Slider(_) = ho.kind {
render_slider(ctx, EDITOR_SCREEN, &self.beatmap, ho)?; let color = graphics::Color::new(1.0, 1.0, 1.0, 0.6 * draw_info.opacity as f32);
render_slider(ctx, EDITOR_SCREEN, &self.beatmap, ho, color)?;
} }
let circ = Mesh::new_circle( let circ = Mesh::new_circle(
@ -121,21 +147,23 @@ impl Game {
pos, pos,
cs_real, cs_real,
1.0, 1.0,
WHITE, color,
)?; )?;
graphics::draw(ctx, &circ, DrawParam::default())?; graphics::draw(ctx, &circ, DrawParam::default())?;
let time_diff = ho_time - time; if time < ho_time {
let approach_r = cs_real * (1.0 + 2.0 * time_diff as f32 / 0.75); let time_diff = ho_time - time;
let approach = Mesh::new_circle( let approach_r = cs_real * (1.0 + 2.0 * time_diff as f32 / 0.75);
ctx, let approach = Mesh::new_circle(
DrawMode::Stroke(StrokeOptions::default()), ctx,
pos, DrawMode::Stroke(StrokeOptions::default().with_line_width(2.0)),
approach_r, pos,
1.0, approach_r,
WHITE, 1.0,
)?; WHITE,
graphics::draw(ctx, &approach, DrawParam::default())?; )?;
graphics::draw(ctx, &approach, DrawParam::default())?;
}
} }
graphics::present(ctx)?; graphics::present(ctx)?;

View file

@ -17,6 +17,7 @@ pub fn render_slider(
rect: Rect, rect: Rect,
beatmap: &Beatmap, beatmap: &Beatmap,
slider: &HitObject, slider: &HitObject,
color: Color,
) -> Result<()> { ) -> Result<()> {
let mut control_points = vec![slider.pos]; let mut control_points = vec![slider.pos];
let slider_info = match &slider.kind { let slider_info = match &slider.kind {
@ -62,12 +63,7 @@ pub fn render_slider(
.with_line_cap(LineCap::Round) .with_line_cap(LineCap::Round)
.with_line_join(LineJoin::Round) .with_line_join(LineJoin::Round)
.with_line_width(cs_real as f32 * 2.0); .with_line_width(cs_real as f32 * 2.0);
let body = Mesh::new_polyline( let body = Mesh::new_polyline(ctx, DrawMode::Stroke(opts), &spline_mapped, color)?;
ctx,
DrawMode::Stroke(opts),
&spline_mapped,
Color::new(1.0, 1.0, 1.0, 0.5),
)?;
graphics::draw(ctx, &body, DrawParam::default())?; graphics::draw(ctx, &body, DrawParam::default())?;
let frame = Mesh::new_polyline( let frame = Mesh::new_polyline(
@ -153,11 +149,12 @@ fn get_spline(
c c
} }
SliderSplineKind::Bezier => { SliderSplineKind::Bezier => {
// split the curve by red-anchors
let mut idx = 0; let mut idx = 0;
let mut whole = Vec::new(); let mut whole = Vec::new();
for i in 1..points.len() { for i in 1..points.len() {
if points[i].0 == points[i - 1].0 && points[i].1 == points[i - 1].1 { if points[i].0 == points[i - 1].0 && points[i].1 == points[i - 1].1 {
let spline = calculate_bezier(&points[idx..i - 1]); let spline = calculate_bezier(&points[idx..i]);
whole.extend(spline); whole.extend(spline);
idx = i; idx = i;
continue; continue;