draw the background image

This commit is contained in:
Michael Zhang 2021-01-13 06:51:33 -06:00
parent 09d26a9022
commit 27859bc05a
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
8 changed files with 77 additions and 9 deletions

10
Cargo.lock generated
View file

@ -830,6 +830,7 @@ dependencies = [
"anyhow", "anyhow",
"bass-sys", "bass-sys",
"ggez", "ggez",
"image",
"libosu", "libosu",
"log", "log",
"num", "num",
@ -1282,10 +1283,12 @@ dependencies = [
"byteorder", "byteorder",
"color_quant", "color_quant",
"gif", "gif",
"jpeg-decoder",
"num-iter", "num-iter",
"num-rational", "num-rational",
"num-traits", "num-traits",
"png", "png",
"scoped_threadpool",
"tiff", "tiff",
] ]
@ -1364,6 +1367,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc797adac5f083b8ff0ca6f6294a999393d76e197c36488e2ef732c4715f6fa3" checksum = "cc797adac5f083b8ff0ca6f6294a999393d76e197c36488e2ef732c4715f6fa3"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"rayon",
] ]
[[package]] [[package]]
@ -2505,6 +2509,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
[[package]]
name = "scoped_threadpool"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.1.0" version = "1.1.0"

View file

@ -22,6 +22,7 @@ stderrlog = "0.5.1"
num = "0.3.1" num = "0.3.1"
ordered-float = "2.0.1" ordered-float = "2.0.1"
structopt = "0.3.21" structopt = "0.3.21"
image = "0.23.12"
[dependencies.libosu] [dependencies.libosu]
git = "https://github.com/iptq/libosu" git = "https://github.com/iptq/libosu"

View file

@ -1,10 +1,18 @@
use anyhow::Result; use anyhow::Result;
use ggez::Context; use ggez::{
graphics::{self, Color, DrawParam},
Context,
};
use super::Game; use super::Game;
impl Game { impl Game {
pub(super) fn draw_background(&self, ctx: &mut Context) -> Result<()> { pub(super) fn draw_background(&self, ctx: &mut Context) -> Result<()> {
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))?;
}
Ok(()) Ok(())
} }
} }

View file

@ -12,10 +12,11 @@ use std::str::FromStr;
use anyhow::Result; use anyhow::Result;
use ggez::{ use ggez::{
event::{EventHandler, KeyCode, KeyMods}, event::{EventHandler, KeyCode, KeyMods, MouseButton},
graphics::{self, Color, DrawParam, FilterMode, Rect, Text, WHITE}, graphics::{self, Color, DrawParam, FilterMode, Image, Rect, Text, WHITE},
Context, GameError, GameResult, Context, GameError, GameResult,
}; };
use image::io::Reader as ImageReader;
use libosu::{ use libosu::{
beatmap::Beatmap, beatmap::Beatmap,
hitobject::{HitObjectKind, SpinnerInfo}, hitobject::{HitObjectKind, SpinnerInfo},
@ -28,6 +29,7 @@ use crate::audio::{AudioEngine, Sound};
use crate::beatmap::{BeatmapExt, STACK_DISTANCE}; use crate::beatmap::{BeatmapExt, STACK_DISTANCE};
use crate::hitobject::HitObjectExt; use crate::hitobject::HitObjectExt;
use crate::skin::Skin; use crate::skin::Skin;
use crate::utils;
pub const PLAYFIELD_BOUNDS: Rect = Rect::new(112.0, 122.0, 800.0, 600.0); pub const PLAYFIELD_BOUNDS: Rect = Rect::new(112.0, 122.0, 800.0, 600.0);
pub const DEFAULT_COLORS: &[(f32, f32, f32)] = &[ pub const DEFAULT_COLORS: &[(f32, f32, f32)] = &[
@ -48,6 +50,7 @@ pub struct Game {
frame: usize, frame: usize,
slider_cache: SliderCache, slider_cache: SliderCache,
combo_colors: Vec<Color>, combo_colors: Vec<Color>,
background_image: Option<Image>,
keymap: HashSet<KeyCode>, keymap: HashSet<KeyCode>,
current_uninherited_timing_point: Option<TimingPoint>, current_uninherited_timing_point: Option<TimingPoint>,
@ -74,6 +77,7 @@ impl Game {
.iter() .iter()
.map(|(r, g, b)| Color::new(*r, *g, *b, 1.0)) .map(|(r, g, b)| Color::new(*r, *g, *b, 1.0))
.collect(), .collect(),
background_image: None,
keymap: HashSet::new(), keymap: HashSet::new(),
current_uninherited_timing_point: None, current_uninherited_timing_point: None,
@ -81,7 +85,7 @@ impl Game {
}) })
} }
pub fn load_beatmap(&mut self, path: impl AsRef<Path>) -> Result<()> { pub fn load_beatmap(&mut self, ctx: &mut Context, path: impl AsRef<Path>) -> Result<()> {
let path = path.as_ref(); let path = path.as_ref();
let mut file = File::open(&path)?; let mut file = File::open(&path)?;
@ -118,6 +122,25 @@ impl Game {
let dir = path.parent().unwrap(); let dir = path.parent().unwrap();
// TODO: more background images possible?
for evt in self.beatmap.inner.events.iter() {
use libosu::events::Event;
if let Event::Background(evt) = evt {
let path = utils::fuck_you_windows(dir, &evt.filename)?;
if let Some(path) = path {
let img = ImageReader::open(path)?.decode()?;
let img_buf = img.into_rgba8();
let image = Image::from_rgba8(
ctx,
img_buf.width() as u16,
img_buf.height() as u16,
img_buf.as_raw(),
)?;
self.background_image = Some(image);
}
}
}
let song = Sound::create(dir.join(&self.beatmap.inner.audio_filename))?; let song = Sound::create(dir.join(&self.beatmap.inner.audio_filename))?;
self.song = Some(song); self.song = Some(song);
self.timestamp_changed()?; self.timestamp_changed()?;
@ -395,6 +418,8 @@ impl EventHandler for Game {
Ok(()) Ok(())
} }
fn mouse_button_down_event(&mut self, ctx: &mut Context, _: MouseButton, x: f32, y: f32) {}
fn key_up_event(&mut self, _: &mut Context, keycode: KeyCode, _: KeyMods) { fn key_up_event(&mut self, _: &mut Context, keycode: KeyCode, _: KeyMods) {
use KeyCode::*; use KeyCode::*;
match keycode { match keycode {

View file

@ -189,7 +189,10 @@ impl Game {
.with_line_width(BOUNDS.h) .with_line_width(BOUNDS.h)
.with_line_cap(LineCap::Round), .with_line_cap(LineCap::Round),
), ),
&[Point2::from([head_x, body_y]), Point2::from([tail_x, body_y])], &[
Point2::from([head_x, body_y]),
Point2::from([tail_x, body_y]),
],
color, color,
)?; )?;
graphics::draw(ctx, &body, DrawParam::default())?; graphics::draw(ctx, &body, DrawParam::default())?;

View file

@ -12,6 +12,7 @@ mod beatmap;
mod game; mod game;
mod hitobject; mod hitobject;
mod skin; mod skin;
mod utils;
use std::path::PathBuf; use std::path::PathBuf;
@ -55,7 +56,7 @@ fn main() -> Result<()> {
game.skin.load_all(&mut ctx)?; game.skin.load_all(&mut ctx)?;
if let Some(path) = opt.path { if let Some(path) = opt.path {
game.load_beatmap(path)?; game.load_beatmap(&mut ctx, path)?;
} }
if let Some(start_time) = opt.start_time { if let Some(start_time) = opt.start_time {

View file

@ -92,9 +92,7 @@ impl Texture {
graphics::draw( graphics::draw(
ctx, ctx,
image, image,
param param.scale([x_scale, y_scale]).offset([0.5, 0.5]),
.scale([x_scale, y_scale])
.offset([0.5, 0.5]),
)?; )?;
Ok(()) Ok(())
} }

22
src/utils.rs Normal file
View file

@ -0,0 +1,22 @@
use std::path::{Path, PathBuf};
use anyhow::Result;
pub fn fuck_you_windows(
parent: impl AsRef<Path>,
name: impl AsRef<str>,
) -> Result<Option<PathBuf>> {
let parent = parent.as_ref();
let name = name.as_ref();
let name_lower = name.to_ascii_lowercase();
for entry in parent.read_dir()? {
let entry = entry?;
let entry_lower = entry.file_name().to_str().unwrap().to_ascii_lowercase();
if name_lower == entry_lower {
return Ok(Some(entry.path()));
}
}
Ok(None)
}