From a45c6301163add38ec84c38a4b25a1bce689daee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Sallai?= Date: Wed, 23 Aug 2023 02:50:03 +0300 Subject: [PATCH] add compact jukebox for non-switch CS+ (#232) --- src/components/compact_jukebox.rs | 86 +++++++++++++++++++++++++++++++ src/components/mod.rs | 1 + src/scene/title_scene.rs | 44 ++++++++++++---- 3 files changed, 122 insertions(+), 9 deletions(-) create mode 100644 src/components/compact_jukebox.rs diff --git a/src/components/compact_jukebox.rs b/src/components/compact_jukebox.rs new file mode 100644 index 0000000..80c715e --- /dev/null +++ b/src/components/compact_jukebox.rs @@ -0,0 +1,86 @@ +use crate::entity::GameEntity; +use crate::framework::context::Context; +use crate::framework::error::GameResult; +use crate::game::frame::Frame; +use crate::game::shared_game_state::SharedGameState; +use crate::graphics::font::Font; + +#[derive(Clone, Copy)] +pub struct CompactJukebox { + song_id: usize, + shown: bool, +} + +impl CompactJukebox { + pub fn new() -> CompactJukebox { + CompactJukebox { song_id: 0, shown: false } + } + + pub fn change_song(&mut self, song_id: usize, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { + self.song_id = song_id; + + if self.song_id == state.sound_manager.current_song() { + return Ok(()); + } + + return state.sound_manager.play_song(song_id, &state.constants, &state.settings, ctx, false); + } + + pub fn next_song(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { + let mut new_song_id = if self.song_id == state.constants.music_table.len() - 1 { 1 } else { self.song_id + 1 }; + + // skip ika if soundtrack is not set to new + if self.is_ika_unavailable(new_song_id, state) { + new_song_id = 1; + } + + self.change_song(new_song_id, state, ctx) + } + + pub fn prev_song(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { + let mut new_song_id = if self.song_id == 1 { state.constants.music_table.len() - 1 } else { self.song_id - 1 }; + + // skip ika if soundtrack is not set to new + if self.is_ika_unavailable(new_song_id, state) { + new_song_id = 42; + } + + self.change_song(new_song_id, state, ctx) + } + + pub fn show(&mut self) { + self.shown = true; + } + + pub fn is_shown(&self) -> bool { + self.shown + } + + fn is_ika_unavailable(&self, song_id: usize, state: &SharedGameState) -> bool { + song_id == 43 && state.settings.soundtrack != "New" + } +} + +impl GameEntity<&mut Context> for CompactJukebox { + fn tick(&mut self, _state: &mut SharedGameState, _ctx: &mut Context) -> GameResult { + Ok(()) + } + + fn draw(&self, state: &mut SharedGameState, ctx: &mut Context, _frame: &Frame) -> GameResult { + if !self.shown { + return Ok(()); + } + + let text = format!("< {:02} >", self.song_id); + + let font_builder = state.font.builder(); + let text_width = font_builder.compute_width(&text); + + let x = state.canvas_size.0 as f32 - text_width - 15.0; + let y = state.canvas_size.1 as f32 - 15.0; + + font_builder.x(x).y(y).shadow(true).draw(&text, ctx, &state.constants, &mut state.texture_set)?; + + Ok(()) + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index ad90e6c..0c7fdae 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -1,5 +1,6 @@ pub mod background; pub mod boss_life_bar; +pub mod compact_jukebox; pub mod credits; pub mod draw_common; pub mod fade; diff --git a/src/scene/title_scene.rs b/src/scene/title_scene.rs index eeaaa30..328e904 100644 --- a/src/scene/title_scene.rs +++ b/src/scene/title_scene.rs @@ -1,5 +1,6 @@ use crate::common::{Color, VERSION_BANNER}; use crate::components::background::Background; +use crate::components::compact_jukebox::CompactJukebox; use crate::components::nikumaru::NikumaruCounter; use crate::entity::GameEntity; use crate::framework::context::Context; @@ -88,6 +89,7 @@ pub struct TitleScene { background: Background, frame: Frame, nikumaru_rec: NikumaruCounter, + compact_jukebox: CompactJukebox, stage: Stage, textures: StageTexturePaths, } @@ -129,6 +131,7 @@ impl TitleScene { background: Background::new(), frame: Frame::new(), nikumaru_rec: NikumaruCounter::new(), + compact_jukebox: CompactJukebox::new(), stage: fake_stage, textures, } @@ -145,13 +148,18 @@ impl TitleScene { Ok(()) } - pub fn update_menu_cursor(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { + pub fn update_menu_cursor(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { let minutes = self.nikumaru_rec.tick / (60 * state.settings.timing_mode.get_tps()); let mut song_id: usize; if self.nikumaru_rec.shown && minutes < 3 { state.menu_character = MenuCharacter::Sue; + song_id = 2; + + if state.constants.is_cs_plus && !state.constants.is_switch { + self.compact_jukebox.show(); + } } else if self.nikumaru_rec.shown && minutes < 4 { state.menu_character = MenuCharacter::King; song_id = 41; @@ -170,9 +178,14 @@ impl TitleScene { song_id = 43; } - if song_id != state.sound_manager.current_song() { - state.sound_manager.play_song(song_id, &state.constants, &state.settings, ctx, false)?; + if self.compact_jukebox.is_shown() { + self.compact_jukebox.change_song(song_id, state, ctx)?; + } else { + if song_id != state.sound_manager.current_song() { + state.sound_manager.play_song(song_id, &state.constants, &state.settings, ctx, false)?; + } } + Ok(()) } @@ -301,6 +314,20 @@ impl Scene for TitleScene { self.challenges_menu.y = ((state.canvas_size.1 + 30.0 - self.challenges_menu.height as f32) / 2.0).floor() as isize; + if self.controller.trigger_left() + && self.compact_jukebox.is_shown() + && self.current_menu == CurrentMenu::MainMenu + { + self.compact_jukebox.prev_song(state, ctx)?; + } + + if self.controller.trigger_right() + && self.compact_jukebox.is_shown() + && self.current_menu == CurrentMenu::MainMenu + { + self.compact_jukebox.next_song(state, ctx)?; + } + match self.current_menu { CurrentMenu::MainMenu => match self.main_menu.tick(&mut self.controller, state) { MenuSelectionResult::Selected(MainMenuEntry::Start, _) => { @@ -461,12 +488,9 @@ impl Scene for TitleScene { if self.current_menu == CurrentMenu::MainMenu { let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "Title")?; - let logo_x_offset = if state.settings.original_textures && state.constants.supports_og_textures { - 20.0 - } else { - 0.0 - }; - + let logo_x_offset = + if state.settings.original_textures && state.constants.supports_og_textures { 20.0 } else { 0.0 }; + batch.add_rect( ((state.canvas_size.0 - state.constants.title.logo_rect.width() as f32) / 2.0).floor() + logo_x_offset, 40.0, @@ -503,6 +527,8 @@ impl Scene for TitleScene { } else { self.draw_text_centered(COPYRIGHT_PIXEL, state.canvas_size.1 - 30.0, state, ctx)?; } + + self.compact_jukebox.draw(state, ctx, &self.frame)?; } self.nikumaru_rec.draw(state, ctx, &self.frame)?;