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>,
beatmap: Beatmap,
hit_objects: Vec<HitObject>,
skin: Skin,
pub skin: Skin,
frame: usize,
slider_cache: SliderCache,
}
@ -45,6 +45,7 @@ impl Game {
hit_objects,
song: None,
skin,
frame: 0,
slider_cache: SliderCache::default(),
})
}
@ -60,7 +61,7 @@ impl Game {
let dir = path.parent().unwrap();
let song = Sound::create(dir.join(&self.beatmap.audio_filename))?;
// song.set_position(36.5)?;
song.set_position(113.0)?;
self.song = Some(song);
Ok(())
@ -79,6 +80,7 @@ impl Game {
fn priv_draw(&mut self, ctx: &mut Context) -> Result<()> {
// TODO: lol
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());
@ -176,15 +178,21 @@ impl Game {
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(
self.skin.sliderb.draw_frame(
ctx,
DrawMode::Fill(FillOptions::default()),
ball_pos,
cs_real,
1.0,
graphics::WHITE,
(cs_real * 2.0, cs_real * 2.0),
DrawParam::default().dest(ball_pos),
(travel_percent / 0.25) as usize,
)?;
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)?;
self.frame += 1;
Ok(())
}
}

View file

@ -35,11 +35,12 @@ fn main() -> Result<()> {
.window_setup(WindowSetup::default().title("OSU editor"))
.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()?;
game.skin.load_all(&mut ctx)?;
let path = env::args().nth(1).unwrap();
game.load_beatmap(path)?;
event::run(ctx, event_loop, &mut game)?;
event::run(&mut ctx, &mut event_loop, &mut game)?;
Ok(())
}

View file

@ -8,7 +8,7 @@ use ggez::{
};
macro_rules! create_skin {
($([$name:ident]),* $(,)?) => {
($([$name:ident, $animatable:expr $(,)?]),* $(,)?) => {
pub struct Skin {
$(
pub $name: Texture,
@ -18,40 +18,80 @@ macro_rules! create_skin {
impl Skin {
pub fn new() -> Self {
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! {
[approachcircle],
[hitcircle],
[hitcircleoverlay],
[approachcircle, false],
[hitcircle, false],
[hitcircleoverlay, false],
[sliderb, true],
}
pub struct Texture {
path: PathBuf,
name: &'static str,
image: Option<Image>,
animatable: bool,
animation: Vec<Image>,
}
impl Texture {
pub fn with_path(path: impl AsRef<Path>) -> Self {
pub fn with_name(name: &'static str, animatable: bool) -> Self {
Texture {
path: path.as_ref().to_path_buf(),
name,
image: None,
animatable,
animation: vec![],
}
}
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()
};
pub fn load(&mut self, ctx: &mut Context) -> Result<()> {
let mut found = false;
if self.animatable {
// god fucking dammit
let hyphen = if self.name == "sliderb" { "" } else { "-" };
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 x_scale = random_constant * size.0 / image.width() as f32;
let y_scale = random_constant * size.1 / image.height() as f32;
@ -64,4 +104,25 @@ impl Texture {
)?;
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)
}
}