load animation for slider ball

This commit is contained in:
Michael Zhang 2021-01-08 09:05:10 -06:00
parent ad0de3d46f
commit 399d80d72c
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
3 changed files with 98 additions and 27 deletions

View file

@ -26,8 +26,8 @@ pub struct Game {
song: Option<Sound>, song: Option<Sound>,
beatmap: Beatmap, beatmap: Beatmap,
hit_objects: Vec<HitObject>, hit_objects: Vec<HitObject>,
skin: Skin, pub skin: Skin,
frame: usize,
slider_cache: SliderCache, slider_cache: SliderCache,
} }
@ -45,6 +45,7 @@ impl Game {
hit_objects, hit_objects,
song: None, song: None,
skin, skin,
frame: 0,
slider_cache: SliderCache::default(), slider_cache: SliderCache::default(),
}) })
} }
@ -60,7 +61,7 @@ impl Game {
let dir = path.parent().unwrap(); let dir = path.parent().unwrap();
let song = Sound::create(dir.join(&self.beatmap.audio_filename))?; let song = Sound::create(dir.join(&self.beatmap.audio_filename))?;
// song.set_position(36.5)?; song.set_position(113.0)?;
self.song = Some(song); self.song = Some(song);
Ok(()) Ok(())
@ -79,6 +80,7 @@ impl Game {
fn priv_draw(&mut self, ctx: &mut Context) -> Result<()> { fn priv_draw(&mut self, ctx: &mut Context) -> Result<()> {
// TODO: lol // TODO: lol
const PLAYFIELD_BOUNDS: Rect = Rect::new(112.0, 112.0, 800.0, 600.0); const PLAYFIELD_BOUNDS: Rect = Rect::new(112.0, 112.0, 800.0, 600.0);
const SEEKER_BOUNDS: Rect = Rect::new(46.0, 722.0, 932.0, 36.0);
graphics::clear(ctx, [0.0, 0.0, 0.0, 1.0].into()); graphics::clear(ctx, [0.0, 0.0, 0.0, 1.0].into());
@ -176,15 +178,21 @@ impl Game {
PLAYFIELD_BOUNDS.x + osupx_scale_x * pos.0 as f32, PLAYFIELD_BOUNDS.x + osupx_scale_x * pos.0 as f32,
PLAYFIELD_BOUNDS.y + osupx_scale_y * pos.1 as f32, PLAYFIELD_BOUNDS.y + osupx_scale_y * pos.1 as f32,
]; ];
let ball = Mesh::new_circle( self.skin.sliderb.draw_frame(
ctx, ctx,
DrawMode::Fill(FillOptions::default()), (cs_real * 2.0, cs_real * 2.0),
ball_pos, DrawParam::default().dest(ball_pos),
cs_real, (travel_percent / 0.25) as usize,
1.0,
graphics::WHITE,
)?; )?;
graphics::draw(ctx, &ball, DrawParam::default())?; // let ball = Mesh::new_circle(
// ctx,
// DrawMode::Fill(FillOptions::default()),
// ball_pos,
// cs_real,
// 1.0,
// graphics::WHITE,
// )?;
// graphics::draw(ctx, &ball, DrawParam::default())?;
} }
} }
@ -212,6 +220,7 @@ impl Game {
} }
graphics::present(ctx)?; graphics::present(ctx)?;
self.frame += 1;
Ok(()) Ok(())
} }
} }

View file

@ -35,11 +35,12 @@ fn main() -> Result<()> {
.window_setup(WindowSetup::default().title("OSU editor")) .window_setup(WindowSetup::default().title("OSU editor"))
.window_mode(WindowMode::default().dimensions(1024.0, 768.0)); .window_mode(WindowMode::default().dimensions(1024.0, 768.0));
let (ctx, event_loop) = &mut cb.build()?; let (mut ctx, mut event_loop) = cb.build()?;
let mut game = Game::new()?; let mut game = Game::new()?;
game.skin.load_all(&mut ctx)?;
let path = env::args().nth(1).unwrap(); let path = env::args().nth(1).unwrap();
game.load_beatmap(path)?; game.load_beatmap(path)?;
event::run(ctx, event_loop, &mut game)?; event::run(&mut ctx, &mut event_loop, &mut game)?;
Ok(()) Ok(())
} }

View file

@ -8,7 +8,7 @@ use ggez::{
}; };
macro_rules! create_skin { macro_rules! create_skin {
($([$name:ident]),* $(,)?) => { ($([$name:ident, $animatable:expr $(,)?]),* $(,)?) => {
pub struct Skin { pub struct Skin {
$( $(
pub $name: Texture, pub $name: Texture,
@ -18,40 +18,80 @@ macro_rules! create_skin {
impl Skin { impl Skin {
pub fn new() -> Self { pub fn new() -> Self {
Skin { Skin {
$($name: Texture::with_path(concat!("/", stringify!($name), ".png")),)* $($name: Texture::with_name(stringify!($name), $animatable),)*
} }
} }
// TODO: do this asynchronously?
pub fn load_all(&mut self, ctx: &mut Context) -> Result<()> {
$(
self.$name.load(ctx)?;
)*
Ok(())
}
} }
} }
} }
create_skin! { create_skin! {
[approachcircle], [approachcircle, false],
[hitcircle], [hitcircle, false],
[hitcircleoverlay], [hitcircleoverlay, false],
[sliderb, true],
} }
pub struct Texture { pub struct Texture {
path: PathBuf, name: &'static str,
image: Option<Image>, image: Option<Image>,
animatable: bool,
animation: Vec<Image>,
} }
impl Texture { impl Texture {
pub fn with_path(path: impl AsRef<Path>) -> Self { pub fn with_name(name: &'static str, animatable: bool) -> Self {
Texture { Texture {
path: path.as_ref().to_path_buf(), name,
image: None, image: None,
animatable,
animation: vec![],
} }
} }
pub fn draw(&mut self, ctx: &mut Context, size: (f32, f32), param: DrawParam) -> Result<()> { pub fn load(&mut self, ctx: &mut Context) -> Result<()> {
let image = if self.image.is_some() { let mut found = false;
self.image.as_ref().unwrap() if self.animatable {
} else { // god fucking dammit
self.image = Some(Image::new(ctx, &self.path)?); let hyphen = if self.name == "sliderb" { "" } else { "-" };
self.image.as_ref().unwrap()
};
self.animation.clear();
let mut curr = 0;
loop {
let image = match Image::new(ctx, &format!("/{}{}{}.png", self.name, hyphen, curr))
{
Ok(v) => v,
Err(_) => break,
};
self.animation.push(image);
found = true;
curr += 1;
}
println!("loaded {} images!", curr);
}
if !found {
self.image = Some(Image::new(ctx, &format!("/{}.png", self.name))?);
}
Ok(())
}
fn draw_image(
&self,
ctx: &mut Context,
image: &Image,
size: (f32, f32),
param: DrawParam,
) -> Result<()> {
let random_constant = 1.35; let random_constant = 1.35;
let x_scale = random_constant * size.0 / image.width() as f32; let x_scale = random_constant * size.0 / image.width() as f32;
let y_scale = random_constant * size.1 / image.height() as f32; let y_scale = random_constant * size.1 / image.height() as f32;
@ -64,4 +104,25 @@ impl Texture {
)?; )?;
Ok(()) Ok(())
} }
pub fn draw(&mut self, ctx: &mut Context, size: (f32, f32), param: DrawParam) -> Result<()> {
let image = self.image.as_ref().unwrap();
self.draw_image(ctx, image, size, param)
}
pub fn draw_frame(
&mut self,
ctx: &mut Context,
size: (f32, f32),
param: DrawParam,
frame: usize,
) -> Result<()> {
let image = if self.animatable {
let ct = frame % self.animation.len();
self.animation.get(ct).unwrap()
} else {
self.image.as_ref().unwrap()
};
self.draw_image(ctx, image, size, param)
}
} }