From a58c77a7060e16b1a27c35d8604bbb2368c73903 Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Wed, 13 Jan 2021 08:20:04 -0600 Subject: [PATCH] kinda implement numbers? they're still off tho --- run.sh | 2 +- src/game/background.rs | 24 ++++++++++++- src/game/mod.rs | 10 ++++-- src/game/numbers.rs | 78 ++++++++++++++++++++++++++++++++++++++++++ src/game/timeline.rs | 8 +++++ src/skin.rs | 48 ++++++++++++++++++++------ 6 files changed, 156 insertions(+), 14 deletions(-) create mode 100644 src/game/numbers.rs diff --git a/run.sh b/run.sh index 8ac11f8..feef0b8 100755 --- a/run.sh +++ b/run.sh @@ -1,4 +1,4 @@ #!/bin/bash export LD_LIBRARY_PATH=$(pwd)/bass-sys/linux/bass24/x64 echo $LD_LIBRARY_PATH -exec cargo run --release "$@" +exec cargo run "$@" diff --git a/src/game/background.rs b/src/game/background.rs index bd46cab..d3752cd 100644 --- a/src/game/background.rs +++ b/src/game/background.rs @@ -8,9 +8,31 @@ use super::Game; impl Game { pub(super) fn draw_background(&self, ctx: &mut Context) -> Result<()> { + let screen_width = 1024; + let screen_height = 768; + let screen_ratio = screen_width as f32 / screen_height as f32; + if let Some(image) = &self.background_image { let dim = Color::new(1.0, 1.0, 1.0, 0.35); - graphics::draw(ctx, image, DrawParam::default().color(dim))?; + let width = image.width(); + let height = image.height(); + let ratio = width as f32 / height as f32; + + let scale = + // background is flatter than screen + if ratio < screen_ratio { + // take screen height + [screen_width as f32/width as f32,screen_height as f32/height as f32] + } + // background is more square than screen + else if ratio > screen_ratio { + [screen_width as f32/width as f32,screen_height as f32/height as f32] + } + // exactly the same ratio + else { + [screen_width as f32/width as f32,screen_height as f32/height as f32] + }; + graphics::draw(ctx, image, DrawParam::default().color(dim).scale(scale))?; } Ok(()) diff --git a/src/game/mod.rs b/src/game/mod.rs index 9860174..c165033 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -1,5 +1,6 @@ mod background; mod grid; +mod numbers; mod seeker; mod sliders; mod timeline; @@ -262,7 +263,7 @@ impl Game { &ho.inner, color, )?; - slider_info = Some((info, control_points, spline)); + slider_info = Some((info, control_points)); let end_pos = ho.inner.end_pos().unwrap(); let end_pos = [ @@ -281,6 +282,7 @@ impl Game { )?; } + // draw main hitcircle self.skin.hitcircle.draw( ctx, (cs_real * 2.0, cs_real * 2.0), @@ -292,7 +294,11 @@ impl Game { DrawParam::default().dest(pos), )?; - if let Some((info, control_points, spline)) = slider_info { + // draw numbers + self.draw_numbers_on_circle(ctx, ho.number, pos, cs_real)?; + + if let Some((info, control_points)) = slider_info { + let spline = self.slider_cache.get(&control_points).unwrap(); Game::render_slider_wireframe(ctx, &control_points, PLAYFIELD_BOUNDS)?; if time > ho_time && time < draw_info.end_time { diff --git a/src/game/numbers.rs b/src/game/numbers.rs new file mode 100644 index 0000000..b7f873f --- /dev/null +++ b/src/game/numbers.rs @@ -0,0 +1,78 @@ +use anyhow::Result; +use ggez::{ + graphics::{self, DrawParam}, + Context, +}; + +use super::Game; + +impl Game { + pub(super) fn draw_numbers_on_circle( + &self, + ctx: &mut Context, + number: usize, + pos: [f32; 2], + cs: f32, + ) -> Result<()> { + let number = number.to_string(); + let digits = number.len(); + let cs = cs / 1.5; + + let mut digits = Vec::new(); + let mut width = 0; + let mut first_height = None; + let spacing = 5; + for digit in number.chars() { + let texture = match digit { + '0' => &self.skin.default0, + '1' => &self.skin.default1, + '2' => &self.skin.default2, + '3' => &self.skin.default3, + '4' => &self.skin.default4, + '5' => &self.skin.default5, + '6' => &self.skin.default6, + '7' => &self.skin.default7, + '8' => &self.skin.default8, + '9' => &self.skin.default9, + _ => unreachable!(), + }; + if let None = first_height { + first_height = Some(texture.height().unwrap()); + } + let this_width = texture.width().unwrap(); + width += this_width + spacing; + digits.push((digit, width, this_width, texture)); + } + + let height = first_height.unwrap(); + let real_total_width = cs * width as f32 / height as f32; + let real_height = cs; + let left_off = pos[0]-real_total_width; + let real_y = pos[1]; + + for (_, x, w, digit) in digits { + let w = w as f32 / height as f32 * cs; + let real_x = left_off + x as f32 / width as f32 * real_total_width; + digit.draw( + ctx, + (w, real_height), + DrawParam::default().dest([real_x, real_y]), + )?; + } + + // let pos = [leftmost + i as f32 / 2.0 * digit_width, pos[1]]; + // let rect = graphics::Mesh::new_rectangle( + // ctx, + // graphics::DrawMode::Stroke(graphics::StrokeOptions::default()), + // [pos[0], pos[1], digit_width, cs].into(), + // [1.0, 0.0, 0.0, 1.0].into(), + // )?; + // graphics::draw(ctx, &rect, DrawParam::default().offset([0.5, 0.5]))?; + // texture.draw( + // ctx, + // (cs * 42.0 / 72.0, cs), + // DrawParam::default().offset([0.5, 0.5]).dest(pos), + // )?; + Ok(()) + } +} diff --git a/src/game/timeline.rs b/src/game/timeline.rs index fb9659f..5f5443c 100644 --- a/src/game/timeline.rs +++ b/src/game/timeline.rs @@ -270,6 +270,14 @@ impl Game { .dest([head_x, timeline_y + BOUNDS.h / 2.0]) .offset([0.5, 0.0]), )?; + + // draw numbers + self.draw_numbers_on_circle( + ctx, + ho.number, + [head_x, timeline_y + BOUNDS.h / 2.0], + BOUNDS.h / 2.0, + )?; } Ok(()) diff --git a/src/skin.rs b/src/skin.rs index 00844f1..2e8f9ba 100644 --- a/src/skin.rs +++ b/src/skin.rs @@ -1,3 +1,5 @@ +use std::path::{Path, PathBuf}; + use anyhow::Result; use ggez::{ graphics::{self, DrawParam, Image}, @@ -5,7 +7,11 @@ use ggez::{ }; macro_rules! create_skin { - ($([$name:ident, $animatable:expr $(,)?]),* $(,)?) => { + ( + // regular skin textures + $( [$name:ident, $path:expr, $animatable:expr $(,)?]),* + $(,)? + ) => { pub struct Skin { $( pub $name: Texture, @@ -15,7 +21,7 @@ macro_rules! create_skin { impl Skin { pub fn new() -> Self { Skin { - $($name: Texture::with_name(stringify!($name), $animatable),)* + $($name: Texture::with_name(stringify!($name), $path, $animatable),)* } } @@ -31,30 +37,52 @@ macro_rules! create_skin { } create_skin! { - [approachcircle, false], - [hitcircle, false], - [hitcircleoverlay, false], - [reversearrow, false], - [sliderb, true], + [approachcircle, "approachcircle", false], + [hitcircle, "hitcircle", false], + [hitcircleoverlay, "hitcircleoverlay", false], + [reversearrow, "reversearrow", false], + [sliderb, "sliderb", true], + + // TODO: actually read numbers from skin.ini + [default0, "default-0", false], + [default1, "default-1", false], + [default2, "default-2", false], + [default3, "default-3", false], + [default4, "default-4", false], + [default5, "default-5", false], + [default6, "default-6", false], + [default7, "default-7", false], + [default8, "default-8", false], + [default9, "default-9", false], } pub struct Texture { name: &'static str, + path: &'static str, image: Option, animatable: bool, animation: Vec, } impl Texture { - pub fn with_name(name: &'static str, animatable: bool) -> Self { + pub fn with_name(name: &'static str, path: &'static str, animatable: bool) -> Self { Texture { name, + path, image: None, animatable, animation: vec![], } } + pub fn width(&self) -> Option { + self.image.as_ref().map(|image| image.width()) + } + + pub fn height(&self) -> Option { + self.image.as_ref().map(|image| image.height()) + } + pub fn load(&mut self, ctx: &mut Context) -> Result<()> { let mut found = false; if self.animatable { @@ -63,7 +91,7 @@ impl Texture { self.animation.clear(); let mut curr = 0; - while let Ok(image) = Image::new(ctx, &format!("/{}{}{}.png", self.name, hyphen, curr)) + while let Ok(image) = Image::new(ctx, &format!("/{}{}{}.png", self.path, hyphen, curr)) { self.animation.push(image); found = true; @@ -73,7 +101,7 @@ impl Texture { } if !found { - self.image = Some(Image::new(ctx, &format!("/{}.png", self.name))?); + self.image = Some(Image::new(ctx, &format!("/{}.png", self.path))?); } Ok(())