add background music
This commit is contained in:
parent
c6d9a002b6
commit
86f2345667
13 changed files with 210 additions and 8 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
|
@ -2046,6 +2046,7 @@ dependencies = [
|
|||
"inhabitant_simbert",
|
||||
"input",
|
||||
"level",
|
||||
"music",
|
||||
"physics",
|
||||
"resource_graveyard",
|
||||
"resource_soul_spot",
|
||||
|
|
@ -3458,6 +3459,15 @@ dependencies = [
|
|||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "music"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bevy",
|
||||
"rand",
|
||||
"state",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "naga"
|
||||
version = "24.0.0"
|
||||
|
|
@ -5411,6 +5421,7 @@ dependencies = [
|
|||
"bevy",
|
||||
"bevy_egui",
|
||||
"combat",
|
||||
"music",
|
||||
"state",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -64,4 +64,5 @@ resource_soul_spot = { path = "crates/resource_soul_spot" }
|
|||
building_ramtower = { path = "crates/building_ramtower" }
|
||||
building_suncannon = { path = "crates/building_suncannon" }
|
||||
ui_menu = { path = "crates/ui_menu" }
|
||||
music = { path = "crates/music" }
|
||||
#new internal crates go here
|
||||
|
|
|
|||
BIN
assets/music/A Very Brady Special.ogg
Normal file
BIN
assets/music/A Very Brady Special.ogg
Normal file
Binary file not shown.
BIN
assets/music/Aquarium.ogg
Normal file
BIN
assets/music/Aquarium.ogg
Normal file
Binary file not shown.
BIN
assets/music/Egmont Overture.ogg
Normal file
BIN
assets/music/Egmont Overture.ogg
Normal file
Binary file not shown.
BIN
assets/music/Ghost Dance.ogg
Normal file
BIN
assets/music/Ghost Dance.ogg
Normal file
Binary file not shown.
BIN
assets/music/Gymnopedie No 3.ogg
Normal file
BIN
assets/music/Gymnopedie No 3.ogg
Normal file
Binary file not shown.
|
|
@ -1,22 +1,22 @@
|
|||
(
|
||||
map: {
|
||||
KeyCode(ShiftLeft): [
|
||||
MultiPlaceTower,
|
||||
],
|
||||
MouseButton(Middle): [
|
||||
CameraOrbitEnable,
|
||||
],
|
||||
KeyCode(F1): [
|
||||
ToggleDebugUI,
|
||||
],
|
||||
MouseButton(Right): [
|
||||
PlaceTower,
|
||||
],
|
||||
MouseButton(Left): [
|
||||
CameraPanEnable,
|
||||
],
|
||||
KeyCode(ShiftLeft): [
|
||||
MultiPlaceTower,
|
||||
],
|
||||
MouseScroll: [
|
||||
CameraZoom,
|
||||
],
|
||||
MouseButton(Left): [
|
||||
CameraPanEnable,
|
||||
KeyCode(F1): [
|
||||
ToggleDebugUI,
|
||||
],
|
||||
MouseMovementX: [
|
||||
CameraYaw,
|
||||
|
|
|
|||
12
crates/music/Cargo.toml
Normal file
12
crates/music/Cargo.toml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "music"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
bevy = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
state = { path = "../state" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
93
crates/music/src/lib.rs
Normal file
93
crates/music/src/lib.rs
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
//bevy system signatures often violate these rules
|
||||
#![allow(clippy::type_complexity)]
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
use bevy::prelude::*;
|
||||
use rand::{Rng, thread_rng};
|
||||
use state::AppState;
|
||||
|
||||
pub struct MusicPlugin;
|
||||
|
||||
impl Plugin for MusicPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_systems(Startup, init)
|
||||
.add_systems(Update, update_track)
|
||||
.add_systems(OnEnter(AppState::Menu), play_menu_music)
|
||||
.add_systems(OnEnter(AppState::Game), play_game_music);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct BackgroundMusicPlayer {
|
||||
menu_music: Vec<Handle<AudioSource>>,
|
||||
game_music: Vec<Handle<AudioSource>>,
|
||||
track_index: usize,
|
||||
}
|
||||
|
||||
fn init(mut commands: Commands, assets: Res<AssetServer>) {
|
||||
commands.spawn(BackgroundMusicPlayer {
|
||||
menu_music: vec![
|
||||
assets.load("music/Gymnopedie No 3.ogg"),
|
||||
assets.load("music/A Very Brady Special.ogg"),
|
||||
],
|
||||
game_music: vec![
|
||||
assets.load("music/Aquarium.ogg"),
|
||||
assets.load("music/Egmont Overture.ogg"),
|
||||
assets.load("music/Ghost Dance.ogg"),
|
||||
],
|
||||
track_index: 0,
|
||||
});
|
||||
}
|
||||
|
||||
fn play_menu_music(
|
||||
player_query: Single<(Entity, &mut BackgroundMusicPlayer)>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
let (player_entity, mut player) = player_query.into_inner();
|
||||
player.track_index = 0;
|
||||
commands
|
||||
.entity(player_entity)
|
||||
.remove::<AudioSink>()
|
||||
.insert(AudioPlayer(player.menu_music[player.track_index].clone()));
|
||||
}
|
||||
|
||||
fn play_game_music(
|
||||
player_query: Single<(Entity, &mut BackgroundMusicPlayer)>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
let (player_entity, mut player) = player_query.into_inner();
|
||||
player.track_index = thread_rng().gen_range(0..player.game_music.len());
|
||||
commands
|
||||
.entity(player_entity)
|
||||
.remove::<AudioSink>()
|
||||
.insert(AudioPlayer(player.game_music[player.track_index].clone()));
|
||||
}
|
||||
|
||||
fn update_track(
|
||||
state: Res<State<AppState>>,
|
||||
player_query: Single<(Entity, &AudioSink, &mut BackgroundMusicPlayer)>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
let (entity, sink, mut background_player) = player_query.into_inner();
|
||||
if sink.empty() {
|
||||
let next_track = match state.get() {
|
||||
AppState::Menu => {
|
||||
background_player.track_index =
|
||||
(background_player.track_index + 1) % background_player.menu_music.len();
|
||||
background_player.menu_music[background_player.track_index].clone()
|
||||
}
|
||||
AppState::Game => {
|
||||
background_player.track_index =
|
||||
(background_player.track_index + 1) % background_player.game_music.len();
|
||||
background_player.game_music[background_player.track_index].clone()
|
||||
}
|
||||
_ => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
commands
|
||||
.entity(entity)
|
||||
.remove::<AudioSink>()
|
||||
.insert(AudioPlayer(next_track));
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ bevy = { workspace = true }
|
|||
bevy_egui = { workspace = true }
|
||||
state = { path = "../state" }
|
||||
combat = { path = "../combat" }
|
||||
music = { path = "../music" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use bevy_egui::{
|
|||
egui::{self, Align2, RichText},
|
||||
};
|
||||
use combat::Difficulty;
|
||||
use music::BackgroundMusicPlayer;
|
||||
use state::AppState;
|
||||
|
||||
pub struct UiMenuPlugin;
|
||||
|
|
@ -22,6 +23,7 @@ impl Plugin for UiMenuPlugin {
|
|||
difficulty_screen.run_if(in_state(MenuScreen::Difficulty)),
|
||||
info_screen.run_if(in_state(MenuScreen::Info)),
|
||||
settings_screen.run_if(in_state(MenuScreen::Settings)),
|
||||
credits_screen.run_if(in_state(MenuScreen::Credits)),
|
||||
),
|
||||
)
|
||||
.add_sub_state::<MenuScreen>();
|
||||
|
|
@ -39,6 +41,7 @@ enum MenuScreen {
|
|||
Info,
|
||||
Difficulty,
|
||||
Settings,
|
||||
Credits,
|
||||
}
|
||||
|
||||
fn setup_menu(mut commands: Commands) {
|
||||
|
|
@ -96,6 +99,14 @@ fn main_screen(mut contexts: EguiContexts, mut next_screen: ResMut<NextState<Men
|
|||
next_screen.set(MenuScreen::Settings);
|
||||
}
|
||||
});
|
||||
ui.centered_and_justified(|ui| {
|
||||
if ui
|
||||
.button(RichText::new("CREDITS").size(VERY_LARGE_FONT_SIZE))
|
||||
.clicked()
|
||||
{
|
||||
next_screen.set(MenuScreen::Credits);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -212,6 +223,7 @@ fn settings_screen(
|
|||
mut contexts: EguiContexts,
|
||||
mut next_screen: ResMut<NextState<MenuScreen>>,
|
||||
mut global_volume: ResMut<GlobalVolume>,
|
||||
mut music_query: Query<&mut AudioSink, With<BackgroundMusicPlayer>>,
|
||||
mut volume: Local<f32>,
|
||||
mut init: Local<bool>,
|
||||
) {
|
||||
|
|
@ -230,6 +242,77 @@ fn settings_screen(
|
|||
ui.label(RichText::new("Volume").size(FONT_SIZE));
|
||||
ui.add(egui::Slider::new(&mut *volume, 0.0..=100.));
|
||||
global_volume.volume = Volume::Linear(*volume / 100.);
|
||||
if let Ok(mut sink) = music_query.single_mut() {
|
||||
sink.set_volume(Volume::Linear(*volume / 100.));
|
||||
}
|
||||
});
|
||||
egui::Window::new("SettingsBack")
|
||||
.resizable(false)
|
||||
.collapsible(false)
|
||||
.title_bar(false)
|
||||
.anchor(Align2::LEFT_TOP, [0., 0.])
|
||||
.show(ctx, |ui| {
|
||||
if ui
|
||||
.button(RichText::new("BACK").size(VERY_LARGE_FONT_SIZE))
|
||||
.clicked()
|
||||
{
|
||||
next_screen.set(MenuScreen::Main);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn credits_screen(mut contexts: EguiContexts, mut next_screen: ResMut<NextState<MenuScreen>>) {
|
||||
let ctx = contexts.ctx_mut().unwrap();
|
||||
egui::Window::new("SettingsScreen")
|
||||
.resizable(false)
|
||||
.collapsible(false)
|
||||
.title_bar(false)
|
||||
.anchor(Align2::CENTER_CENTER, [0., 0.])
|
||||
.fixed_size([800., 100.])
|
||||
.show(ctx, |ui| {
|
||||
ui.heading("Created by Jim Moore");
|
||||
ui.heading("Music (in game)");
|
||||
ui.label(
|
||||
RichText::new(
|
||||
"\"Aquarium\" Kevin MacLeod (incompetech.com)
|
||||
Licensed under Creative Commons: By Attribution 4.0 License
|
||||
http://creativecommons.org/licenses/by/4.0/",
|
||||
)
|
||||
.size(FONT_SIZE),
|
||||
);
|
||||
ui.label(
|
||||
RichText::new(
|
||||
"\"Egmont Overture\" Kevin MacLeod (incompetech.com)
|
||||
Licensed under Creative Commons: By Attribution 4.0 License
|
||||
http://creativecommons.org/licenses/by/4.0/",
|
||||
)
|
||||
.size(FONT_SIZE),
|
||||
);
|
||||
ui.label(
|
||||
RichText::new(
|
||||
"\"Ghost Dance\" Kevin MacLeod (incompetech.com)
|
||||
Licensed under Creative Commons: By Attribution 4.0 License
|
||||
http://creativecommons.org/licenses/by/4.0/",
|
||||
)
|
||||
.size(FONT_SIZE),
|
||||
);
|
||||
ui.heading("Music (menu)");
|
||||
ui.label(
|
||||
RichText::new(
|
||||
"\"Gymnopedie No. 3\" Kevin MacLeod (incompetech.com)
|
||||
Licensed under Creative Commons: By Attribution 4.0 License
|
||||
http://creativecommons.org/licenses/by/4.0/",
|
||||
)
|
||||
.size(FONT_SIZE),
|
||||
);
|
||||
ui.label(
|
||||
RichText::new(
|
||||
"\"A Very Brady Special\" Kevin MacLeod (incompetech.com)
|
||||
Licensed under Creative Commons: By Attribution 4.0 License
|
||||
http://creativecommons.org/licenses/by/4.0/",
|
||||
)
|
||||
.size(FONT_SIZE),
|
||||
);
|
||||
});
|
||||
egui::Window::new("SettingsBack")
|
||||
.resizable(false)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ fn main() {
|
|||
building_ramtower::BuildingRamtowerPlugin,
|
||||
building_suncannon::BuildingSuncannonPlugin,
|
||||
ui_menu::UiMenuPlugin,
|
||||
music::MusicPlugin,
|
||||
// new internal crates go here
|
||||
));
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue