simplify audio system
This commit is contained in:
parent
3bbc57d29f
commit
13fbe226e9
208
src/audio.rs
208
src/audio.rs
|
@ -13,22 +13,7 @@
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::audio::{PlaybackMode, Volume};
|
use bevy::audio::{PlaybackMode, Volume};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use std::collections::HashMap;
|
||||||
const ASSET_CLICK: &str = "sounds/click-button-140881-crop.ogg";
|
|
||||||
const ASSET_SWITCH: &str = "sounds/typosonic-typing-192811-crop.ogg";
|
|
||||||
const ASSET_WOOSH: &str = "sounds/woosh.ogg";
|
|
||||||
const ASSET_ZOOM: &str = "sounds/zoom.ogg";
|
|
||||||
const ASSET_INCOMING_MESSAGE: &str = "sounds/connect.ogg";
|
|
||||||
const ASSET_PING: &str = "sounds/connect.ogg";
|
|
||||||
const ASSET_CONNECT: &str = "sounds/connect.ogg";
|
|
||||||
const ASSET_BGM: &str = "music/Aleksey Chistilin - Cinematic Cello.ogg";
|
|
||||||
const ASSET_THRUSTER: &str = "sounds/thruster.ogg";
|
|
||||||
const ASSET_ROCKET: &str = "sounds/rocket.ogg";
|
|
||||||
const ASSET_ION: &str = "sounds/ion.ogg";
|
|
||||||
const ASSET_WAKEUP: &str = "sounds/wakeup.ogg";
|
|
||||||
const ASSET_BIKESTART: &str = "sounds/bikestart.ogg";
|
|
||||||
const ASSET_CRASH: &str = "sounds/crash.ogg";
|
|
||||||
const ASSET_ELECTRICMOTOR: &str = "sounds/electricmotor.ogg";
|
|
||||||
|
|
||||||
pub struct AudioPlugin;
|
pub struct AudioPlugin;
|
||||||
impl Plugin for AudioPlugin {
|
impl Plugin for AudioPlugin {
|
||||||
|
@ -47,48 +32,83 @@ impl Plugin for AudioPlugin {
|
||||||
|
|
||||||
#[derive(Resource)] pub struct ZoomTimer(Timer);
|
#[derive(Resource)] pub struct ZoomTimer(Timer);
|
||||||
|
|
||||||
|
const PATHS: &[(SfxType, Sfx, &str)] = &[
|
||||||
|
(SfxType::BGM, Sfx::BGM, "music/Aleksey Chistilin - Cinematic Cello.ogg"),
|
||||||
|
(SfxType::LoopSfx, Sfx::ElectricMotor, "sounds/electricmotor.ogg"),
|
||||||
|
(SfxType::LoopSfx, Sfx::Ion, "sounds/ion.ogg"),
|
||||||
|
(SfxType::LoopSfx, Sfx::Rocket, "sounds/rocket.ogg"),
|
||||||
|
(SfxType::LoopSfx, Sfx::Thruster, "sounds/thruster.ogg"),
|
||||||
|
(SfxType::OneOff, Sfx::Click, "sounds/click-button-140881-crop.ogg"),
|
||||||
|
(SfxType::OneOff, Sfx::Connect, "sounds/connect.ogg"),
|
||||||
|
(SfxType::OneOff, Sfx::Crash, "sounds/crash.ogg"),
|
||||||
|
(SfxType::OneOff, Sfx::EnterVehicle, "sounds/bikestart.ogg"),
|
||||||
|
(SfxType::OneOff, Sfx::IncomingChatMessage, "sounds/connect.ogg"),
|
||||||
|
(SfxType::OneOff, Sfx::Ping, "sounds/connect.ogg"),
|
||||||
|
(SfxType::OneOff, Sfx::Switch, "sounds/typosonic-typing-192811-crop.ogg"),
|
||||||
|
(SfxType::OneOff, Sfx::WakeUp, "sounds/wakeup.ogg"),
|
||||||
|
(SfxType::OneOff, Sfx::Woosh, "sounds/woosh.ogg"),
|
||||||
|
(SfxType::OneOff, Sfx::Zoom, "sounds/zoom.ogg"),
|
||||||
|
];
|
||||||
|
|
||||||
|
#[derive(Component, PartialEq, Hash, Eq, Copy, Clone)]
|
||||||
pub enum Sfx {
|
pub enum Sfx {
|
||||||
IncomingChatMessage,
|
BGM,
|
||||||
Click,
|
Click,
|
||||||
|
Connect,
|
||||||
|
Crash,
|
||||||
|
ElectricMotor,
|
||||||
|
EnterVehicle,
|
||||||
|
IncomingChatMessage,
|
||||||
|
Ion,
|
||||||
|
Ping,
|
||||||
|
Rocket,
|
||||||
Switch,
|
Switch,
|
||||||
|
Thruster,
|
||||||
|
WakeUp,
|
||||||
Woosh,
|
Woosh,
|
||||||
Zoom,
|
Zoom,
|
||||||
Ping,
|
}
|
||||||
Connect,
|
|
||||||
EnterVehicle,
|
pub fn str2sfx(sfx_label: &str) -> Sfx {
|
||||||
Crash,
|
return match sfx_label {
|
||||||
WakeUp,
|
"switch" => Sfx::Switch,
|
||||||
None,
|
"click" => Sfx::Click,
|
||||||
|
"woosh" => Sfx::Woosh,
|
||||||
|
"zoom" => Sfx::Zoom,
|
||||||
|
"chat" => Sfx::IncomingChatMessage,
|
||||||
|
"ping" => Sfx::Ping,
|
||||||
|
"connect" => Sfx::Connect,
|
||||||
|
"entervehicle" => Sfx::EnterVehicle,
|
||||||
|
"crash" => Sfx::Ping,
|
||||||
|
_ => Sfx::Click,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum SfxType {
|
||||||
|
BGM,
|
||||||
|
LoopSfx,
|
||||||
|
OneOff,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Event)] pub struct PlaySfxEvent(pub Sfx);
|
#[derive(Event)] pub struct PlaySfxEvent(pub Sfx);
|
||||||
#[derive(Event)] pub struct ToggleMusicEvent();
|
#[derive(Event)] pub struct ToggleMusicEvent();
|
||||||
#[derive(Component)] pub struct ComponentBGM;
|
#[derive(Resource)] pub struct Sounds(HashMap<Sfx, Handle<AudioSource>>);
|
||||||
#[derive(Component)] pub struct ComponentThrusterSound;
|
|
||||||
#[derive(Component)] pub struct ComponentRocketSound;
|
|
||||||
#[derive(Component)] pub struct ComponentIonSound;
|
|
||||||
#[derive(Component)] pub struct ComponentElectricMotorSound;
|
|
||||||
#[derive(Component)] struct SoundBGM(Handle<AudioSource>);
|
|
||||||
#[derive(Resource)] pub struct SoundClick(Handle<AudioSource>);
|
|
||||||
#[derive(Resource)] pub struct SoundSwitch(Handle<AudioSource>);
|
|
||||||
#[derive(Resource)] pub struct SoundWoosh(Handle<AudioSource>);
|
|
||||||
#[derive(Resource)] pub struct SoundZoom(Handle<AudioSource>);
|
|
||||||
#[derive(Resource)] pub struct SoundIncomingMessage(Handle<AudioSource>);
|
|
||||||
#[derive(Resource)] pub struct SoundPing(Handle<AudioSource>);
|
|
||||||
#[derive(Resource)] pub struct SoundConnect(Handle<AudioSource>);
|
|
||||||
#[derive(Resource)] pub struct SoundBikeStart(Handle<AudioSource>);
|
|
||||||
#[derive(Resource)] pub struct SoundCrash(Handle<AudioSource>);
|
|
||||||
#[derive(Resource)] pub struct SoundWakeUp(Handle<AudioSource>);
|
|
||||||
|
|
||||||
pub fn setup(
|
pub fn setup(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
settings: Res<var::Settings>,
|
settings: Res<var::Settings>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
) {
|
) {
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
for (sfxtype, sfx, path) in PATHS {
|
||||||
|
let source = asset_server.load(*path);
|
||||||
|
map.insert(*sfx, source.clone());
|
||||||
|
match sfxtype {
|
||||||
|
SfxType::BGM => {
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
ComponentBGM,
|
*sfx,
|
||||||
AudioBundle {
|
AudioBundle {
|
||||||
source: SoundBGM(asset_server.load(ASSET_BGM)).0.clone(),
|
source,
|
||||||
settings: PlaybackSettings {
|
settings: PlaybackSettings {
|
||||||
mode: PlaybackMode::Loop,
|
mode: PlaybackMode::Loop,
|
||||||
paused: settings.mute_music,
|
paused: settings.mute_music,
|
||||||
|
@ -96,10 +116,12 @@ pub fn setup(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
},
|
||||||
|
SfxType::LoopSfx => {
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
ComponentThrusterSound,
|
*sfx,
|
||||||
AudioBundle {
|
AudioBundle {
|
||||||
source: asset_server.load(ASSET_THRUSTER),
|
source,
|
||||||
settings: PlaybackSettings {
|
settings: PlaybackSettings {
|
||||||
mode: PlaybackMode::Loop,
|
mode: PlaybackMode::Loop,
|
||||||
volume: Volume::new(0.0),
|
volume: Volume::new(0.0),
|
||||||
|
@ -108,52 +130,11 @@ pub fn setup(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
commands.spawn((
|
|
||||||
ComponentRocketSound,
|
|
||||||
AudioBundle {
|
|
||||||
source: asset_server.load(ASSET_ROCKET),
|
|
||||||
settings: PlaybackSettings {
|
|
||||||
mode: PlaybackMode::Loop,
|
|
||||||
volume: Volume::new(0.0),
|
|
||||||
paused: true,
|
|
||||||
..default()
|
|
||||||
},
|
},
|
||||||
},
|
SfxType::OneOff => ()
|
||||||
));
|
}
|
||||||
commands.spawn((
|
}
|
||||||
ComponentIonSound,
|
commands.insert_resource(Sounds(map));
|
||||||
AudioBundle {
|
|
||||||
source: asset_server.load(ASSET_ION),
|
|
||||||
settings: PlaybackSettings {
|
|
||||||
mode: PlaybackMode::Loop,
|
|
||||||
volume: Volume::new(0.0),
|
|
||||||
paused: true,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
));
|
|
||||||
commands.spawn((
|
|
||||||
ComponentElectricMotorSound,
|
|
||||||
AudioBundle {
|
|
||||||
source: asset_server.load(ASSET_ELECTRICMOTOR),
|
|
||||||
settings: PlaybackSettings {
|
|
||||||
mode: PlaybackMode::Loop,
|
|
||||||
volume: Volume::new(0.5),
|
|
||||||
paused: true,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
));
|
|
||||||
commands.insert_resource(SoundClick(asset_server.load(ASSET_CLICK)));
|
|
||||||
commands.insert_resource(SoundSwitch(asset_server.load(ASSET_SWITCH)));
|
|
||||||
commands.insert_resource(SoundWoosh(asset_server.load(ASSET_WOOSH)));
|
|
||||||
commands.insert_resource(SoundZoom(asset_server.load(ASSET_ZOOM)));
|
|
||||||
commands.insert_resource(SoundIncomingMessage(asset_server.load(ASSET_INCOMING_MESSAGE)));
|
|
||||||
commands.insert_resource(SoundPing(asset_server.load(ASSET_PING)));
|
|
||||||
commands.insert_resource(SoundConnect(asset_server.load(ASSET_CONNECT)));
|
|
||||||
commands.insert_resource(SoundBikeStart(asset_server.load(ASSET_BIKESTART)));
|
|
||||||
commands.insert_resource(SoundCrash(asset_server.load(ASSET_CRASH)));
|
|
||||||
commands.insert_resource(SoundWakeUp(asset_server.load(ASSET_WAKEUP)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle_bgm(
|
pub fn toggle_bgm(
|
||||||
|
@ -178,67 +159,32 @@ pub fn play_sfx(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
settings: Res<var::Settings>,
|
settings: Res<var::Settings>,
|
||||||
mut events_sfx: EventReader<PlaySfxEvent>,
|
mut events_sfx: EventReader<PlaySfxEvent>,
|
||||||
sound_click: Res<SoundClick>,
|
sounds: Res<Sounds>,
|
||||||
sound_switch: Res<SoundSwitch>,
|
|
||||||
sound_woosh: Res<SoundWoosh>,
|
|
||||||
sound_zoom: Res<SoundZoom>,
|
|
||||||
sound_incoming_message: Res<SoundIncomingMessage>,
|
|
||||||
sound_ping: Res<SoundPing>,
|
|
||||||
sound_connect: Res<SoundConnect>,
|
|
||||||
sound_bikestart: Res<SoundBikeStart>,
|
|
||||||
sound_crash: Res<SoundCrash>,
|
|
||||||
sound_wakeup: Res<SoundWakeUp>,
|
|
||||||
) {
|
) {
|
||||||
if settings.mute_sfx && !events_sfx.is_empty() {
|
if settings.mute_sfx && !events_sfx.is_empty() {
|
||||||
events_sfx.clear();
|
events_sfx.clear();
|
||||||
}
|
}
|
||||||
for sfx in events_sfx.read() {
|
for sfx in events_sfx.read() {
|
||||||
match sfx.0 {
|
if let Some(source) = sounds.0.get(&sfx.0) {
|
||||||
Sfx::None => { continue; }
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
commands.spawn(AudioBundle {
|
commands.spawn(AudioBundle {
|
||||||
source: match sfx.0 {
|
source: source.clone(),
|
||||||
Sfx::Switch => sound_switch.0.clone(),
|
|
||||||
Sfx::Click => sound_click.0.clone(),
|
|
||||||
Sfx::Woosh => sound_woosh.0.clone(),
|
|
||||||
Sfx::Zoom => sound_zoom.0.clone(),
|
|
||||||
Sfx::IncomingChatMessage => sound_incoming_message.0.clone(),
|
|
||||||
Sfx::Ping => sound_ping.0.clone(),
|
|
||||||
Sfx::Connect => sound_connect.0.clone(),
|
|
||||||
Sfx::EnterVehicle => sound_bikestart.0.clone(),
|
|
||||||
Sfx::Crash => sound_crash.0.clone(),
|
|
||||||
Sfx::WakeUp => sound_wakeup.0.clone(),
|
|
||||||
Sfx::None => sound_ping.0.clone(),
|
|
||||||
},
|
|
||||||
settings: PlaybackSettings::DESPAWN,
|
settings: PlaybackSettings::DESPAWN,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn str2sfx(sfx_label: &str) -> Sfx {
|
|
||||||
return match sfx_label {
|
|
||||||
"switch" => Sfx::Switch,
|
|
||||||
"click" => Sfx::Click,
|
|
||||||
"woosh" => Sfx::Woosh,
|
|
||||||
"zoom" => Sfx::Zoom,
|
|
||||||
"chat" => Sfx::IncomingChatMessage,
|
|
||||||
"ping" => Sfx::Ping,
|
|
||||||
"connect" => Sfx::Connect,
|
|
||||||
"entervehicle" => Sfx::EnterVehicle,
|
|
||||||
"crash" => Sfx::Crash,
|
|
||||||
_ => Sfx::None,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_music(
|
pub fn update_music(
|
||||||
mut events: EventReader<ToggleMusicEvent>,
|
mut events: EventReader<ToggleMusicEvent>,
|
||||||
bgm_controller: Query<&AudioSink, With<ComponentBGM>>,
|
q_audiosinks: Query<(&AudioSink, &Sfx)>,
|
||||||
settings: Res<var::Settings>,
|
settings: Res<var::Settings>,
|
||||||
) {
|
) {
|
||||||
if !events.is_empty() {
|
if !events.is_empty() {
|
||||||
events.clear();
|
events.clear();
|
||||||
if let Ok(bgm_sink) = bgm_controller.get_single() {
|
for (bgm_sink, sfx) in &q_audiosinks {
|
||||||
|
if *sfx != Sfx::BGM {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if settings.mute_music {
|
if settings.mute_music {
|
||||||
bgm_sink.pause();
|
bgm_sink.pause();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ use bevy::transform::TransformSystem;
|
||||||
use bevy_xpbd_3d::prelude::*;
|
use bevy_xpbd_3d::prelude::*;
|
||||||
use bevy_xpbd_3d::plugins::sync;
|
use bevy_xpbd_3d::plugins::sync;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub const INITIAL_ZOOM_LEVEL: f64 = 10.0;
|
pub const INITIAL_ZOOM_LEVEL: f64 = 10.0;
|
||||||
|
|
||||||
|
@ -379,10 +380,7 @@ pub fn apply_input_to_player(
|
||||||
windows: Query<&Window, With<PrimaryWindow>>,
|
windows: Query<&Window, With<PrimaryWindow>>,
|
||||||
mut mouse_events: EventReader<MouseMotion>,
|
mut mouse_events: EventReader<MouseMotion>,
|
||||||
key_input: Res<ButtonInput<KeyCode>>,
|
key_input: Res<ButtonInput<KeyCode>>,
|
||||||
thruster_sound_controller: Query<&AudioSink, With<audio::ComponentThrusterSound>>,
|
q_audiosinks: Query<(&audio::Sfx, &AudioSink)>,
|
||||||
rocket_sound_controller: Query<&AudioSink, With<audio::ComponentRocketSound>>,
|
|
||||||
ion_sound_controller: Query<&AudioSink, With<audio::ComponentIonSound>>,
|
|
||||||
electricmotor_sound_controller: Query<&AudioSink, With<audio::ComponentElectricMotorSound>>,
|
|
||||||
q_target: Query<&LinearVelocity, (With<hud::IsTargeted>, Without<actor::PlayerCamera>)>,
|
q_target: Query<&LinearVelocity, (With<hud::IsTargeted>, Without<actor::PlayerCamera>)>,
|
||||||
mut q_playercam: Query<(
|
mut q_playercam: Query<(
|
||||||
&Transform,
|
&Transform,
|
||||||
|
@ -550,8 +548,13 @@ pub fn apply_input_to_player(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut sinks: HashMap<audio::Sfx, &AudioSink> = HashMap::new();
|
||||||
|
for (sfx, sink) in &q_audiosinks {
|
||||||
|
sinks.insert(*sfx, sink);
|
||||||
|
}
|
||||||
|
|
||||||
// Play sound effects
|
// Play sound effects
|
||||||
if let Ok(sink) = electricmotor_sound_controller.get_single() {
|
if let Some(sink) = sinks.get(&audio::Sfx::ElectricMotor) {
|
||||||
let volume = sink.volume();
|
let volume = sink.volume();
|
||||||
let speed = sink.speed();
|
let speed = sink.speed();
|
||||||
let action = pitch_yaw_rot.length_squared().powf(0.2) * 0.0005;
|
let action = pitch_yaw_rot.length_squared().powf(0.2) * 0.0005;
|
||||||
|
@ -569,14 +572,14 @@ pub fn apply_input_to_player(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let sinks = vec![
|
let sinks = vec![
|
||||||
(1.2, actor::EngineType::Monopropellant, thruster_sound_controller.get_single()),
|
(1.2, actor::EngineType::Monopropellant, sinks.get(&audio::Sfx::Thruster)),
|
||||||
(1.0, actor::EngineType::Rocket, rocket_sound_controller.get_single()),
|
(1.0, actor::EngineType::Rocket, sinks.get(&audio::Sfx::Rocket)),
|
||||||
(1.4, actor::EngineType::Ion, ion_sound_controller.get_single()),
|
(1.4, actor::EngineType::Ion, sinks.get(&audio::Sfx::Ion)),
|
||||||
];
|
];
|
||||||
let seconds_to_max_vol = 0.05;
|
let seconds_to_max_vol = 0.05;
|
||||||
let seconds_to_min_vol = 0.05;
|
let seconds_to_min_vol = 0.05;
|
||||||
for sink_data in sinks {
|
for sink_data in sinks {
|
||||||
if let (vol_boost, engine_type, Ok(sink)) = sink_data {
|
if let (vol_boost, engine_type, Some(sink)) = sink_data {
|
||||||
if settings.mute_sfx {
|
if settings.mute_sfx {
|
||||||
sink.pause();
|
sink.pause();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue