notch hell
This commit is contained in:
parent
7914d2bafb
commit
e0875cd09e
6 changed files with 66 additions and 31 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -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",
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
72
src/game.rs
72
src/game.rs
|
@ -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)?;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue