2024-04-21 16:23:40 +00:00
|
|
|
// ▄████████▄ + ███ + ▄█████████ ███ +
|
|
|
|
// ███▀ ▀███ + + ███ ███▀ + ███ + +
|
|
|
|
// ███ + ███ ███ ███ █████████ ███ ███ ███ ███
|
2024-04-21 17:34:00 +00:00
|
|
|
// ███ +███ ███ ███ ███ ███▐██████ ███ ███ ███
|
2024-04-21 16:23:40 +00:00
|
|
|
// ███ + ███ ███+ ███ +███ ███ + ███ ███ + ███
|
|
|
|
// ███▄ ▄███ ███▄ ███ ███ + ███ + ███ ███▄ ███
|
|
|
|
// ▀████████▀ + ▀███████ ███▄ ███▄ ▀████ ▀███████
|
|
|
|
// + + + ███
|
|
|
|
// + ▀████████████████████████████████████████████████████▀
|
2024-04-23 15:33:36 +00:00
|
|
|
//
|
|
|
|
// This module manages sound effects and music.
|
2024-04-21 16:23:40 +00:00
|
|
|
|
2024-03-16 19:53:57 +00:00
|
|
|
use bevy::prelude::*;
|
2024-03-31 00:07:35 +00:00
|
|
|
use bevy::audio::{PlaybackMode, Volume};
|
2024-04-14 12:55:00 +00:00
|
|
|
use crate::var;
|
2024-03-16 19:53:57 +00:00
|
|
|
|
2024-03-18 01:24:52 +00:00
|
|
|
const ASSET_CLICK: &str = "sounds/click-button-140881-crop.ogg";
|
|
|
|
const ASSET_SWITCH: &str = "sounds/typosonic-typing-192811-crop.ogg";
|
2024-03-19 22:32:12 +00:00
|
|
|
const ASSET_INCOMING_MESSAGE: &str = "sounds/connect.ogg";
|
|
|
|
const ASSET_PING: &str = "sounds/connect.ogg";
|
2024-03-22 12:57:29 +00:00
|
|
|
const ASSET_CONNECT: &str = "sounds/connect.ogg";
|
2024-04-03 12:21:28 +00:00
|
|
|
const ASSET_BGM: &str = "music/Aleksey Chistilin - Cinematic Cello.ogg";
|
2024-03-19 22:32:12 +00:00
|
|
|
const ASSET_THRUSTER: &str = "sounds/thruster.ogg";
|
2024-03-28 13:10:10 +00:00
|
|
|
const ASSET_ROCKET: &str = "sounds/rocket.ogg";
|
2024-03-29 03:36:20 +00:00
|
|
|
const ASSET_ION: &str = "sounds/ion.ogg";
|
2024-04-05 01:31:52 +00:00
|
|
|
const ASSET_WAKEUP: &str = "sounds/wakeup.ogg";
|
2024-03-28 13:19:53 +00:00
|
|
|
const ASSET_BIKESTART: &str = "sounds/bikestart.ogg";
|
2024-03-29 15:58:42 +00:00
|
|
|
const ASSET_CRASH: &str = "sounds/crash.ogg";
|
2024-03-31 00:07:35 +00:00
|
|
|
const ASSET_ELECTRICMOTOR: &str = "sounds/electricmotor.ogg";
|
2024-03-18 01:15:44 +00:00
|
|
|
|
2024-03-17 23:04:23 +00:00
|
|
|
pub struct AudioPlugin;
|
|
|
|
impl Plugin for AudioPlugin {
|
|
|
|
fn build(&self, app: &mut App) {
|
|
|
|
app.add_systems(Startup, setup);
|
|
|
|
app.add_systems(Update, toggle_bgm);
|
2024-03-18 01:15:44 +00:00
|
|
|
app.add_systems(PostUpdate, play_sfx);
|
2024-03-18 02:01:47 +00:00
|
|
|
app.add_systems(PostUpdate, update_music);
|
2024-03-19 02:18:16 +00:00
|
|
|
app.add_event::<PlaySfxEvent>();
|
2024-03-18 02:01:47 +00:00
|
|
|
app.add_event::<ToggleMusicEvent>();
|
2024-03-17 23:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-19 02:18:16 +00:00
|
|
|
pub enum Sfx {
|
|
|
|
IncomingChatMessage,
|
|
|
|
Click,
|
|
|
|
Switch,
|
2024-03-19 04:38:11 +00:00
|
|
|
Ping,
|
2024-03-19 05:24:27 +00:00
|
|
|
Connect,
|
2024-03-28 12:26:14 +00:00
|
|
|
EnterVehicle,
|
2024-03-29 15:58:42 +00:00
|
|
|
Crash,
|
2024-04-05 01:31:52 +00:00
|
|
|
WakeUp,
|
2024-03-19 04:38:11 +00:00
|
|
|
None,
|
2024-03-19 02:18:16 +00:00
|
|
|
}
|
2024-03-18 00:52:41 +00:00
|
|
|
|
2024-03-19 02:18:16 +00:00
|
|
|
#[derive(Event)] pub struct PlaySfxEvent(pub Sfx);
|
|
|
|
#[derive(Event)] pub struct ToggleMusicEvent();
|
|
|
|
#[derive(Component)] pub struct ComponentBGM;
|
|
|
|
#[derive(Component)] pub struct ComponentThrusterSound;
|
2024-03-28 13:10:10 +00:00
|
|
|
#[derive(Component)] pub struct ComponentRocketSound;
|
2024-03-29 03:36:20 +00:00
|
|
|
#[derive(Component)] pub struct ComponentIonSound;
|
2024-03-31 00:07:35 +00:00
|
|
|
#[derive(Component)] pub struct ComponentElectricMotorSound;
|
2024-03-19 02:18:16 +00:00
|
|
|
#[derive(Component)] struct SoundBGM(Handle<AudioSource>);
|
|
|
|
#[derive(Resource)] pub struct SoundClick(Handle<AudioSource>);
|
|
|
|
#[derive(Resource)] pub struct SoundSwitch(Handle<AudioSource>);
|
|
|
|
#[derive(Resource)] pub struct SoundIncomingMessage(Handle<AudioSource>);
|
2024-03-19 04:38:11 +00:00
|
|
|
#[derive(Resource)] pub struct SoundPing(Handle<AudioSource>);
|
2024-03-19 05:24:27 +00:00
|
|
|
#[derive(Resource)] pub struct SoundConnect(Handle<AudioSource>);
|
2024-03-28 13:19:53 +00:00
|
|
|
#[derive(Resource)] pub struct SoundBikeStart(Handle<AudioSource>);
|
2024-03-29 15:58:42 +00:00
|
|
|
#[derive(Resource)] pub struct SoundCrash(Handle<AudioSource>);
|
2024-04-05 01:31:52 +00:00
|
|
|
#[derive(Resource)] pub struct SoundWakeUp(Handle<AudioSource>);
|
2024-03-18 01:15:44 +00:00
|
|
|
|
2024-03-16 19:53:57 +00:00
|
|
|
pub fn setup(
|
|
|
|
mut commands: Commands,
|
2024-04-14 12:55:00 +00:00
|
|
|
settings: Res<var::Settings>,
|
2024-03-16 19:53:57 +00:00
|
|
|
asset_server: Res<AssetServer>,
|
|
|
|
) {
|
|
|
|
commands.spawn((
|
2024-03-18 02:01:47 +00:00
|
|
|
ComponentBGM,
|
2024-03-16 19:53:57 +00:00
|
|
|
AudioBundle {
|
2024-03-18 02:01:47 +00:00
|
|
|
source: SoundBGM(asset_server.load(ASSET_BGM)).0.clone(),
|
|
|
|
settings: PlaybackSettings {
|
|
|
|
mode: PlaybackMode::Loop,
|
2024-03-18 03:10:08 +00:00
|
|
|
paused: settings.hud_active || settings.mute_music,
|
2024-03-18 02:01:47 +00:00
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
));
|
2024-03-16 23:41:06 +00:00
|
|
|
commands.spawn((
|
|
|
|
ComponentThrusterSound,
|
|
|
|
AudioBundle {
|
2024-03-19 17:27:13 +00:00
|
|
|
source: asset_server.load(ASSET_THRUSTER),
|
2024-03-16 23:41:06 +00:00
|
|
|
settings: PlaybackSettings {
|
|
|
|
mode: PlaybackMode::Loop,
|
2024-04-15 19:55:46 +00:00
|
|
|
volume: Volume::new(0.0),
|
2024-03-16 23:41:06 +00:00
|
|
|
paused: true,
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
));
|
2024-03-28 13:10:10 +00:00
|
|
|
commands.spawn((
|
|
|
|
ComponentRocketSound,
|
|
|
|
AudioBundle {
|
|
|
|
source: asset_server.load(ASSET_ROCKET),
|
|
|
|
settings: PlaybackSettings {
|
|
|
|
mode: PlaybackMode::Loop,
|
2024-04-15 19:55:46 +00:00
|
|
|
volume: Volume::new(0.0),
|
2024-03-28 13:10:10 +00:00
|
|
|
paused: true,
|
|
|
|
..default()
|
2024-03-29 03:36:20 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
));
|
|
|
|
commands.spawn((
|
|
|
|
ComponentIonSound,
|
|
|
|
AudioBundle {
|
|
|
|
source: asset_server.load(ASSET_ION),
|
|
|
|
settings: PlaybackSettings {
|
|
|
|
mode: PlaybackMode::Loop,
|
2024-04-15 19:55:46 +00:00
|
|
|
volume: Volume::new(0.0),
|
2024-03-29 03:36:20 +00:00
|
|
|
paused: true,
|
|
|
|
..default()
|
2024-03-28 13:10:10 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
));
|
2024-03-31 00:07:35 +00:00
|
|
|
commands.spawn((
|
|
|
|
ComponentElectricMotorSound,
|
|
|
|
AudioBundle {
|
|
|
|
source: asset_server.load(ASSET_ELECTRICMOTOR),
|
|
|
|
settings: PlaybackSettings {
|
|
|
|
mode: PlaybackMode::Loop,
|
|
|
|
volume: Volume::new(0.5),
|
|
|
|
paused: true,
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
));
|
2024-03-18 01:15:44 +00:00
|
|
|
commands.insert_resource(SoundClick(asset_server.load(ASSET_CLICK)));
|
|
|
|
commands.insert_resource(SoundSwitch(asset_server.load(ASSET_SWITCH)));
|
2024-03-19 02:18:16 +00:00
|
|
|
commands.insert_resource(SoundIncomingMessage(asset_server.load(ASSET_INCOMING_MESSAGE)));
|
2024-03-19 04:38:11 +00:00
|
|
|
commands.insert_resource(SoundPing(asset_server.load(ASSET_PING)));
|
2024-03-19 05:24:27 +00:00
|
|
|
commands.insert_resource(SoundConnect(asset_server.load(ASSET_CONNECT)));
|
2024-03-28 13:19:53 +00:00
|
|
|
commands.insert_resource(SoundBikeStart(asset_server.load(ASSET_BIKESTART)));
|
2024-03-29 15:58:42 +00:00
|
|
|
commands.insert_resource(SoundCrash(asset_server.load(ASSET_CRASH)));
|
2024-04-05 01:31:52 +00:00
|
|
|
commands.insert_resource(SoundWakeUp(asset_server.load(ASSET_WAKEUP)));
|
2024-03-16 19:53:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn toggle_bgm(
|
|
|
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
2024-03-18 02:01:47 +00:00
|
|
|
mut evwriter_toggle: EventWriter<ToggleMusicEvent>,
|
2024-03-19 02:18:16 +00:00
|
|
|
mut evwriter_sfx: EventWriter<PlaySfxEvent>,
|
2024-04-14 12:55:00 +00:00
|
|
|
mut settings: ResMut<var::Settings>,
|
2024-03-16 19:53:57 +00:00
|
|
|
) {
|
2024-04-20 02:48:17 +00:00
|
|
|
if keyboard_input.just_pressed(settings.key_toggle_music) {
|
2024-03-18 02:01:47 +00:00
|
|
|
settings.mute_music ^= true;
|
2024-03-19 02:18:16 +00:00
|
|
|
evwriter_sfx.send(PlaySfxEvent(Sfx::Click));
|
2024-03-18 02:01:47 +00:00
|
|
|
evwriter_toggle.send(ToggleMusicEvent());
|
2024-03-16 19:53:57 +00:00
|
|
|
}
|
2024-04-20 02:48:17 +00:00
|
|
|
if keyboard_input.just_pressed(settings.key_toggle_sfx) {
|
2024-03-18 03:10:08 +00:00
|
|
|
settings.mute_sfx ^= true;
|
2024-03-19 02:18:16 +00:00
|
|
|
evwriter_sfx.send(PlaySfxEvent(Sfx::Click));
|
2024-03-18 03:10:08 +00:00
|
|
|
evwriter_toggle.send(ToggleMusicEvent());
|
|
|
|
}
|
2024-03-16 19:53:57 +00:00
|
|
|
}
|
2024-03-18 00:52:41 +00:00
|
|
|
|
2024-03-18 01:15:44 +00:00
|
|
|
pub fn play_sfx(
|
2024-03-18 00:52:41 +00:00
|
|
|
mut commands: Commands,
|
2024-04-14 12:55:00 +00:00
|
|
|
settings: Res<var::Settings>,
|
2024-03-19 02:18:16 +00:00
|
|
|
mut events_sfx: EventReader<PlaySfxEvent>,
|
2024-03-18 01:15:44 +00:00
|
|
|
sound_click: Res<SoundClick>,
|
|
|
|
sound_switch: Res<SoundSwitch>,
|
2024-03-19 02:18:16 +00:00
|
|
|
sound_incoming_message: Res<SoundIncomingMessage>,
|
2024-03-19 04:38:11 +00:00
|
|
|
sound_ping: Res<SoundPing>,
|
2024-03-19 05:24:27 +00:00
|
|
|
sound_connect: Res<SoundConnect>,
|
2024-03-28 13:19:53 +00:00
|
|
|
sound_bikestart: Res<SoundBikeStart>,
|
2024-03-29 15:58:42 +00:00
|
|
|
sound_crash: Res<SoundCrash>,
|
2024-04-05 01:31:52 +00:00
|
|
|
sound_wakeup: Res<SoundWakeUp>,
|
2024-03-18 00:52:41 +00:00
|
|
|
) {
|
2024-03-19 02:18:16 +00:00
|
|
|
if settings.mute_sfx && !events_sfx.is_empty() {
|
|
|
|
events_sfx.clear();
|
2024-03-18 01:15:44 +00:00
|
|
|
}
|
2024-03-19 02:18:16 +00:00
|
|
|
for sfx in events_sfx.read() {
|
2024-03-20 05:42:39 +00:00
|
|
|
match sfx.0 {
|
|
|
|
Sfx::None => { continue; }
|
|
|
|
_ => {}
|
|
|
|
}
|
2024-03-19 02:18:16 +00:00
|
|
|
commands.spawn(AudioBundle {
|
|
|
|
source: match sfx.0 {
|
|
|
|
Sfx::Switch => sound_switch.0.clone(),
|
|
|
|
Sfx::Click => sound_click.0.clone(),
|
|
|
|
Sfx::IncomingChatMessage => sound_incoming_message.0.clone(),
|
2024-03-19 04:38:11 +00:00
|
|
|
Sfx::Ping => sound_ping.0.clone(),
|
2024-03-19 05:24:27 +00:00
|
|
|
Sfx::Connect => sound_connect.0.clone(),
|
2024-03-28 13:19:53 +00:00
|
|
|
Sfx::EnterVehicle => sound_bikestart.0.clone(),
|
2024-03-29 15:58:42 +00:00
|
|
|
Sfx::Crash => sound_crash.0.clone(),
|
2024-04-05 01:31:52 +00:00
|
|
|
Sfx::WakeUp => sound_wakeup.0.clone(),
|
2024-03-19 04:38:11 +00:00
|
|
|
Sfx::None => sound_ping.0.clone(),
|
2024-03-19 02:18:16 +00:00
|
|
|
},
|
|
|
|
settings: PlaybackSettings::DESPAWN,
|
|
|
|
});
|
2024-03-18 00:52:41 +00:00
|
|
|
}
|
|
|
|
}
|
2024-03-18 02:01:47 +00:00
|
|
|
|
2024-03-19 04:38:11 +00:00
|
|
|
pub fn str2sfx(sfx_label: &str) -> Sfx {
|
|
|
|
return match sfx_label {
|
|
|
|
"switch" => Sfx::Switch,
|
|
|
|
"click" => Sfx::Click,
|
|
|
|
"chat" => Sfx::IncomingChatMessage,
|
|
|
|
"ping" => Sfx::Ping,
|
2024-03-19 05:24:27 +00:00
|
|
|
"connect" => Sfx::Connect,
|
2024-03-28 12:26:14 +00:00
|
|
|
"entervehicle" => Sfx::EnterVehicle,
|
2024-03-29 15:58:42 +00:00
|
|
|
"crash" => Sfx::Crash,
|
2024-03-19 04:38:11 +00:00
|
|
|
_ => Sfx::None,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2024-03-18 02:01:47 +00:00
|
|
|
pub fn update_music(
|
|
|
|
mut events: EventReader<ToggleMusicEvent>,
|
|
|
|
bgm_controller: Query<&AudioSink, With<ComponentBGM>>,
|
2024-04-14 12:55:00 +00:00
|
|
|
settings: Res<var::Settings>,
|
2024-03-18 02:01:47 +00:00
|
|
|
) {
|
|
|
|
if !events.is_empty() {
|
|
|
|
events.clear();
|
|
|
|
if let Ok(bgm_sink) = bgm_controller.get_single() {
|
2024-03-28 19:03:40 +00:00
|
|
|
if settings.mute_music {
|
|
|
|
bgm_sink.pause();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bgm_sink.play();
|
2024-03-18 02:01:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|