diff --git a/Cargo.lock b/Cargo.lock index 807f125b71..63fda22145 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4932,26 +4932,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17033fe05e4f7f10a6ad602c272bafd2520b2e5cdd9feb61494d9cdce08e002f" dependencies = [ "lazy_static", - "symphonia-bundle-mp3", "symphonia-codec-vorbis", "symphonia-core", "symphonia-format-ogg", "symphonia-metadata", ] -[[package]] -name = "symphonia-bundle-mp3" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db5d3d53535ae2b7d0e39e82f683cac5398a6c8baca25ff1183e107d13959d3e" -dependencies = [ - "bitflags", - "lazy_static", - "log", - "symphonia-core", - "symphonia-metadata", -] - [[package]] name = "symphonia-codec-vorbis" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index d93626f8f4..b45225b1ae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,8 +24,6 @@ render = [ ] [dependencies] -tracing = { version = "0.1.37", features = ["release_max_level_debug"]} -log = { version = "0.4.17", features = ["release_max_level_debug"] } anyhow = "1.0.58" async-channel = "1.7.1" base64 = "0.13.0" @@ -37,7 +35,7 @@ bevy_ecs_tilemap = { version = "0.7.0", features = ["atlas"] } bevy_egui = "0.16.1" bevy_fluent = "0.4.0" bevy_ggrs = { git = "https://github.com/zicklag/bevy_ggrs.git", branch = "jumpy" } -bevy_kira_audio = { version = "0.12.0", features = ["mp3"] } +bevy_kira_audio = { version = "0.12.0", features = ["ogg"], default-features = false } bevy_mod_js_scripting = { git = "https://github.com/zicklag/bevy_mod_js_scripting.git", branch = "jumpy" } bevy_prototype_lyon = "0.6.0" bevy_tweening = { version = "0.5", default-features = false } @@ -56,6 +54,8 @@ getrandom = { version = "0.2", features = ["js"] } iyes_loopless = "0.8.0" jumpy-matchmaker-proto = { path = "crates/matchmaker-proto" } leafwing-input-manager = { version = "0.6.1", default-features = false } +log = { version = "0.4.17", features = ["release_max_level_debug"] } +mimalloc = { version = "0.1.32", default-features = false } normalize-path = "0.2.0" numquant = "0.2.0" once_cell = "1.13.0" @@ -66,9 +66,9 @@ serde = { version = "1.0.137", features = ["derive"] } serde_yaml = "0.9.2" sys-locale = "0.2.1" thiserror = "1.0.31" -unic-langid = "0.9.0" +tracing = { version = "0.1.37", features = ["release_max_level_debug"] } turborand = { version = "0.8.0", features = ["atomic", "serialize"] } -mimalloc = { version = "0.1.32", default-features = false } +unic-langid = "0.9.0" [dependencies.bevy] version = "0.8" @@ -97,4 +97,5 @@ lto = true codegen-units = 1 # Improved rapier physics perf, so it might help other stuff, too [patch.crates-io] +# Fix for https://github.com/bevyengine/bevy/issues/6790 bevy_hierarchy = { git = "https://github.com/zicklag/bevy.git", branch = "dont-error-on-non-mapped-children-entities" } diff --git a/assets/default.game.yaml b/assets/default.game.yaml index eda8a3fd1b..d68516142c 100644 --- a/assets/default.game.yaml +++ b/assets/default.game.yaml @@ -18,6 +18,7 @@ stable_maps: - map/levels/level2.map.yaml - map/levels/level3.map.yaml - map/levels/level4.map.yaml + experimental_maps: # - map/levels/lev01.map.json # Renamed to Level 1 - map/levels/lev02.map.json @@ -33,6 +34,17 @@ experimental_maps: - map/levels/zyrafa05.map.json # - map/levels/zyrafa06.map.json # Renamed to Level 2 +playlist: + - music/across_the_pond.ogg + - music/ahoy!.ogg + - music/bait_the_hook.ogg + - music/fish_and_ships.ogg + - music/fish_bowl.ogg + - music/fish_tide.ogg + - music/fishsticks.ogg + - music/krill_or_be_krilled.ogg + - music/whale_theme.ogg + scripts: - map/scripts/kill_out_of_bounds.ts - ui/menu-background-zoom.ts diff --git a/assets/music/across_the_pond.ogg b/assets/music/across_the_pond.ogg new file mode 100644 index 0000000000..bda10e4605 Binary files /dev/null and b/assets/music/across_the_pond.ogg differ diff --git a/assets/music/ahoy!.ogg b/assets/music/ahoy!.ogg new file mode 100644 index 0000000000..b25ca92adb Binary files /dev/null and b/assets/music/ahoy!.ogg differ diff --git a/assets/music/bait_the_hook.ogg b/assets/music/bait_the_hook.ogg new file mode 100644 index 0000000000..2d9e39117a Binary files /dev/null and b/assets/music/bait_the_hook.ogg differ diff --git a/assets/music/fish_and_ships.ogg b/assets/music/fish_and_ships.ogg new file mode 100644 index 0000000000..7d887dd00c Binary files /dev/null and b/assets/music/fish_and_ships.ogg differ diff --git a/assets/music/fish_bowl.ogg b/assets/music/fish_bowl.ogg new file mode 100644 index 0000000000..fb0d88a06f Binary files /dev/null and b/assets/music/fish_bowl.ogg differ diff --git a/assets/music/fish_tide.ogg b/assets/music/fish_tide.ogg new file mode 100644 index 0000000000..9d8d5bdcc9 Binary files /dev/null and b/assets/music/fish_tide.ogg differ diff --git a/assets/music/fishsticks.ogg b/assets/music/fishsticks.ogg new file mode 100644 index 0000000000..caf1f6b426 Binary files /dev/null and b/assets/music/fishsticks.ogg differ diff --git a/assets/music/krill_or_be_krilled.ogg b/assets/music/krill_or_be_krilled.ogg new file mode 100644 index 0000000000..65e8870f41 Binary files /dev/null and b/assets/music/krill_or_be_krilled.ogg differ diff --git a/assets/music/thanks_for_all_the_fished.ogg b/assets/music/thanks_for_all_the_fished.ogg new file mode 100644 index 0000000000..6503402f97 Binary files /dev/null and b/assets/music/thanks_for_all_the_fished.ogg differ diff --git a/assets/music/whale_theme.ogg b/assets/music/whale_theme.ogg new file mode 100644 index 0000000000..7dcac7e68a Binary files /dev/null and b/assets/music/whale_theme.ogg differ diff --git a/src/assets.rs b/src/assets.rs index d6ba426732..145070ace9 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -137,6 +137,13 @@ impl AssetLoader for GameMetaLoader { ); dependencies.push(main_menu_background_path); + // Load the music playlist + for song in &meta.playlist { + let (path, handle) = get_relative_asset(load_context, self_path, song); + dependencies.push(path.clone()); + meta.playlist_handles.push(handle.typed()); + } + // Load UI border images let mut load_border_image = |border: &mut BorderImageMeta| { let (path, handle) = get_relative_asset(load_context, self_path, &border.image); diff --git a/src/audio.rs b/src/audio.rs new file mode 100644 index 0000000000..a5b7980f18 --- /dev/null +++ b/src/audio.rs @@ -0,0 +1,64 @@ +use std::time::Duration; + +use bevy_kira_audio::{ + AudioApp, AudioChannel, AudioControl, AudioInstance, AudioSource, PlaybackState, +}; +use rand::{seq::SliceRandom, thread_rng}; + +use crate::{metadata::GameMeta, prelude::*}; + +pub struct AudioPlugin; + +impl Plugin for AudioPlugin { + fn build(&self, app: &mut App) { + app.add_plugin(bevy_kira_audio::AudioPlugin) + .init_resource::() + .init_resource::() + .add_audio_channel::() + .add_system(music_system.run_if_resource_exists::()); + } +} + +pub struct MusicChannel; + +#[derive(Clone, Debug, Default)] +pub struct CurrentMusic { + pub instance: Handle, + pub idx: usize, +} + +#[derive(Deref, DerefMut, Clone, Debug, Default)] +pub struct ShuffledPlaylist(pub Vec>); + +/// Loops through all the game music as the game is on. +fn music_system( + game: Res, + mut playlist: ResMut, + mut current_music: ResMut, + audio_instances: Res>, + music: Res>, +) { + if playlist.is_empty() { + let mut songs = game.playlist_handles.clone(); + songs.shuffle(&mut thread_rng()); + **playlist = songs; + } + + if let Some(instance) = audio_instances.get(¤t_music.instance) { + if let PlaybackState::Stopped = instance.state() { + current_music.idx += 1; + current_music.idx %= playlist.len(); + + current_music.instance = music + .play(playlist[current_music.idx].clone()) + .linear_fade_in(Duration::from_secs_f32(0.5)) + .handle(); + } + } else if let Some(song) = playlist.get(0) { + current_music.instance = music + .play(song.clone()) + .linear_fade_in(Duration::from_secs_f32(0.5)) + .handle(); + current_music.idx = 0; + } +} diff --git a/src/main.rs b/src/main.rs index 4d9b4d651a..a8d75a1275 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,6 +26,7 @@ static GLOBAL: MiMalloc = MiMalloc; pub mod animation; pub mod assets; +pub mod audio; pub mod camera; pub mod config; pub mod damage; @@ -55,6 +56,7 @@ pub mod workarounds; use crate::{ animation::AnimationPlugin, assets::AssetPlugin, + audio::AudioPlugin, camera::CameraPlugin, damage::DamagePlugin, debug::DebugPlugin, @@ -211,6 +213,7 @@ pub fn main() { .add_plugin(UiPlugin); app.add_plugin(bevy_tweening::TweeningPlugin) + .add_plugin(AudioPlugin) .add_plugin(UtilsPlugin) .add_plugin(MetadataPlugin) .add_plugin(PlatformPlugin) diff --git a/src/metadata.rs b/src/metadata.rs index 069b67dcb7..e900eb3b27 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -4,6 +4,7 @@ use crate::prelude::*; use bevy::{reflect::TypeUuid, utils::HashMap}; use bevy_has_load_progress::HasLoadProgress; +use bevy_kira_audio::AudioSource; use bevy_mod_js_scripting::JsScript; mod localization; @@ -47,6 +48,9 @@ pub struct GameMeta { pub main_menu: MainMenuMeta, pub default_settings: settings::Settings, pub physics: PhysicsMeta, + pub playlist: Vec, + #[serde(skip)] + pub playlist_handles: Vec>, /// Scripts that run on both the server and the client #[serde(default)]