fix the slider ball not moving correctly
This commit is contained in:
parent
69fd5a452a
commit
aef8e2e6c6
6 changed files with 105 additions and 32 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1038,7 +1038,7 @@ checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"
|
|||
[[package]]
|
||||
name = "libosu"
|
||||
version = "0.0.12"
|
||||
source = "git+https://github.com/iptq/libosu?rev=fa82d6b167c648ad3f68efa3005aa8f7af12d943#fa82d6b167c648ad3f68efa3005aa8f7af12d943"
|
||||
source = "git+https://github.com/iptq/libosu?rev=d75fe384e95156b3b40dd9e5ca7af539e48af8fa#d75fe384e95156b3b40dd9e5ca7af539e48af8fa"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags",
|
||||
|
|
|
@ -20,4 +20,4 @@ ordered-float = "2.0.1"
|
|||
|
||||
[dependencies.libosu]
|
||||
git = "https://github.com/iptq/libosu"
|
||||
rev = "fa82d6b167c648ad3f68efa3005aa8f7af12d943"
|
||||
rev = "d75fe384e95156b3b40dd9e5ca7af539e48af8fa"
|
||||
|
|
54
src/game.rs
54
src/game.rs
|
@ -10,11 +10,13 @@ use ggez::{
|
|||
self, Color, DrawMode, DrawParam, FillOptions, FilterMode, Mesh, Rect, StrokeOptions, Text,
|
||||
WHITE,
|
||||
},
|
||||
nalgebra::Point2,
|
||||
Context, GameError, GameResult,
|
||||
};
|
||||
use libosu::{Beatmap, HitObject, HitObjectKind, Point, SpinnerInfo};
|
||||
|
||||
use crate::audio::{AudioEngine, Sound};
|
||||
use crate::skin::Skin;
|
||||
use crate::slider_render::{render_slider, Spline};
|
||||
|
||||
pub type SliderCache = HashMap<Vec<Point<i32>>, Spline>;
|
||||
|
@ -25,6 +27,7 @@ pub struct Game {
|
|||
song: Option<Sound>,
|
||||
beatmap: Beatmap,
|
||||
hit_objects: Vec<HitObject>,
|
||||
skin: Skin,
|
||||
|
||||
slider_cache: SliderCache,
|
||||
}
|
||||
|
@ -34,6 +37,7 @@ impl Game {
|
|||
let audio_engine = AudioEngine::new()?;
|
||||
let beatmap = Beatmap::default();
|
||||
let hit_objects = Vec::new();
|
||||
let skin = Skin::new();
|
||||
|
||||
Ok(Game {
|
||||
is_playing: false,
|
||||
|
@ -41,6 +45,7 @@ impl Game {
|
|||
beatmap,
|
||||
hit_objects,
|
||||
song: None,
|
||||
skin,
|
||||
slider_cache: SliderCache::default(),
|
||||
})
|
||||
}
|
||||
|
@ -56,7 +61,7 @@ impl Game {
|
|||
let dir = path.parent().unwrap();
|
||||
|
||||
let song = Sound::create(dir.join(&self.beatmap.audio_filename))?;
|
||||
song.set_position(113.0)?;
|
||||
song.set_position(36.5)?;
|
||||
self.song = Some(song);
|
||||
|
||||
Ok(())
|
||||
|
@ -74,14 +79,14 @@ impl Game {
|
|||
|
||||
fn priv_draw(&mut self, ctx: &mut Context) -> Result<()> {
|
||||
// TODO: lol
|
||||
const EDITOR_SCREEN: Rect = Rect::new(112.0, 84.0, 800.0, 600.0);
|
||||
const PLAYFIELD_BOUNDS: Rect = Rect::new(112.0, 112.0, 800.0, 600.0);
|
||||
|
||||
graphics::clear(ctx, [0.0, 0.0, 0.0, 1.0].into());
|
||||
|
||||
let playfield = Mesh::new_rectangle(
|
||||
ctx,
|
||||
DrawMode::Stroke(StrokeOptions::default()),
|
||||
EDITOR_SCREEN,
|
||||
PLAYFIELD_BOUNDS,
|
||||
Color::new(1.0, 1.0, 1.0, 0.5),
|
||||
)?;
|
||||
graphics::draw(ctx, &playfield, DrawParam::default())?;
|
||||
|
@ -128,9 +133,9 @@ impl Game {
|
|||
}
|
||||
}
|
||||
|
||||
let cs_scale = EDITOR_SCREEN.w / 640.0;
|
||||
let osupx_scale_x = EDITOR_SCREEN.w / 512.0;
|
||||
let osupx_scale_y = EDITOR_SCREEN.h / 384.0;
|
||||
let cs_scale = PLAYFIELD_BOUNDS.w / 640.0;
|
||||
let osupx_scale_x = PLAYFIELD_BOUNDS.w / 512.0;
|
||||
let osupx_scale_y = PLAYFIELD_BOUNDS.h / 384.0;
|
||||
let cs_osupx = self.beatmap.difficulty.circle_size_osupx();
|
||||
let cs_real = cs_osupx * cs_scale;
|
||||
|
||||
|
@ -138,8 +143,8 @@ impl Game {
|
|||
let ho = draw_info.hit_object;
|
||||
let ho_time = (ho.start_time.0 as f64) / 1000.0;
|
||||
let pos = [
|
||||
EDITOR_SCREEN.x + osupx_scale_x * ho.pos.0 as f32,
|
||||
EDITOR_SCREEN.y + osupx_scale_y * ho.pos.1 as f32,
|
||||
PLAYFIELD_BOUNDS.x + osupx_scale_x * ho.pos.0 as f32,
|
||||
PLAYFIELD_BOUNDS.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);
|
||||
|
||||
|
@ -148,7 +153,7 @@ impl Game {
|
|||
let spline = render_slider(
|
||||
&mut self.slider_cache,
|
||||
ctx,
|
||||
EDITOR_SCREEN,
|
||||
PLAYFIELD_BOUNDS,
|
||||
&self.beatmap,
|
||||
ho,
|
||||
color,
|
||||
|
@ -166,10 +171,11 @@ impl Game {
|
|||
travel_percent = 1.0 - travel_percent;
|
||||
}
|
||||
let travel_length = travel_percent * info.pixel_length;
|
||||
print!("ho={:.3} ", ho_time);
|
||||
let pos = spline.point_at_length(travel_length);
|
||||
let ball_pos = [
|
||||
EDITOR_SCREEN.x + osupx_scale_x * pos.0 as f32,
|
||||
EDITOR_SCREEN.y + osupx_scale_y * pos.1 as f32,
|
||||
PLAYFIELD_BOUNDS.x + osupx_scale_x * pos.0 as f32,
|
||||
PLAYFIELD_BOUNDS.y + osupx_scale_y * pos.1 as f32,
|
||||
];
|
||||
let ball = Mesh::new_circle(
|
||||
ctx,
|
||||
|
@ -183,28 +189,26 @@ impl Game {
|
|||
}
|
||||
}
|
||||
|
||||
let circ = Mesh::new_circle(
|
||||
self.skin.hitcircle.draw(
|
||||
ctx,
|
||||
DrawMode::Fill(FillOptions::default()),
|
||||
pos,
|
||||
cs_real,
|
||||
1.0,
|
||||
color,
|
||||
(cs_real * 2.0, cs_real * 2.0),
|
||||
DrawParam::default().dest(pos).color(color),
|
||||
)?;
|
||||
|
||||
self.skin.hitcircleoverlay.draw(
|
||||
ctx,
|
||||
(cs_real * 2.0, cs_real * 2.0),
|
||||
DrawParam::default().dest(pos).color(color),
|
||||
)?;
|
||||
graphics::draw(ctx, &circ, DrawParam::default())?;
|
||||
|
||||
if time < ho_time {
|
||||
let time_diff = ho_time - time;
|
||||
let approach_r = cs_real * (1.0 + 2.0 * time_diff as f32 / 0.75);
|
||||
let approach = Mesh::new_circle(
|
||||
self.skin.approachcircle.draw(
|
||||
ctx,
|
||||
DrawMode::Stroke(StrokeOptions::default().with_line_width(2.0)),
|
||||
pos,
|
||||
approach_r,
|
||||
1.0,
|
||||
WHITE,
|
||||
(approach_r * 2.0, approach_r * 2.0),
|
||||
DrawParam::default().dest(pos).color(color),
|
||||
)?;
|
||||
graphics::draw(ctx, &approach, DrawParam::default())?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,8 @@ fn main() -> Result<()> {
|
|||
.init()
|
||||
.unwrap();
|
||||
|
||||
let cb = ContextBuilder::new("super_simple", "ggez")
|
||||
let cb = ContextBuilder::new("osu_editor", "ggez")
|
||||
.add_resource_path("skin")
|
||||
.window_setup(WindowSetup::default().title("OSU editor"))
|
||||
.window_mode(WindowMode::default().dimensions(1024.0, 768.0));
|
||||
|
||||
|
|
68
src/skin.rs
68
src/skin.rs
|
@ -1 +1,67 @@
|
|||
pub struct Skin {}
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use anyhow::Result;
|
||||
use ggez::{
|
||||
graphics::{self, DrawParam, Image},
|
||||
nalgebra::Point2,
|
||||
Context,
|
||||
};
|
||||
|
||||
macro_rules! create_skin {
|
||||
($([$name:ident]),* $(,)?) => {
|
||||
pub struct Skin {
|
||||
$(
|
||||
pub $name: Texture,
|
||||
)*
|
||||
}
|
||||
|
||||
impl Skin {
|
||||
pub fn new() -> Self {
|
||||
Skin {
|
||||
$($name: Texture::with_path(concat!("/", stringify!($name), ".png")),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
create_skin! {
|
||||
[approachcircle],
|
||||
[hitcircle],
|
||||
[hitcircleoverlay],
|
||||
}
|
||||
|
||||
pub struct Texture {
|
||||
path: PathBuf,
|
||||
image: Option<Image>,
|
||||
}
|
||||
|
||||
impl Texture {
|
||||
pub fn with_path(path: impl AsRef<Path>) -> Self {
|
||||
Texture {
|
||||
path: path.as_ref().to_path_buf(),
|
||||
image: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(&mut self, ctx: &mut Context, size: (f32, f32), param: DrawParam) -> Result<()> {
|
||||
let image = if self.image.is_some() {
|
||||
self.image.as_ref().unwrap()
|
||||
} else {
|
||||
self.image = Some(Image::new(ctx, &self.path)?);
|
||||
self.image.as_ref().unwrap()
|
||||
};
|
||||
|
||||
let random_constant = 1.35;
|
||||
let x_scale = random_constant * size.0 / image.width() as f32;
|
||||
let y_scale = random_constant * size.1 / image.height() as f32;
|
||||
graphics::draw(
|
||||
ctx,
|
||||
image,
|
||||
param
|
||||
.scale([x_scale, y_scale])
|
||||
.offset(Point2::new(0.5, 0.5)),
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -230,8 +230,6 @@ impl Spline {
|
|||
let n = self.spline_points.len() - 1;
|
||||
if idx == 0 && self.spline_points.len() > 2 {
|
||||
return self.spline_points[0];
|
||||
} else if idx >= n {
|
||||
return self.spline_points[n];
|
||||
}
|
||||
|
||||
let (len1, len2) = (
|
||||
|
@ -240,7 +238,11 @@ impl Spline {
|
|||
);
|
||||
let proportion = (length - len1) / (len2 - len1);
|
||||
|
||||
let (p1, p2) = (self.spline_points[idx], self.spline_points[idx + 1]);
|
||||
let (p1, p2) = (self.spline_points[idx - 1], self.spline_points[idx]);
|
||||
// println!(
|
||||
// "len={:.3} idx={} len1={:.3} len2={:.3} prop={:.3} p1={:.3} p2={:.3}",
|
||||
// length, idx, len1, len2, proportion, p1, p2
|
||||
// );
|
||||
assert!(p1 != p2);
|
||||
(p2 - p1) * proportion + p1
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue