From 13fbe226e9d9d00c0591638a223db785b8487ccc Mon Sep 17 00:00:00 2001 From: hut Date: Mon, 13 May 2024 04:20:18 +0200 Subject: [PATCH] simplify audio system --- src/audio.rs | 250 ++++++++++++++++++++------------------------------ src/camera.rs | 21 +++-- 2 files changed, 110 insertions(+), 161 deletions(-) diff --git a/src/audio.rs b/src/audio.rs index 24a6ac8..65b93a7 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -13,22 +13,7 @@ use bevy::prelude::*; use bevy::audio::{PlaybackMode, Volume}; use crate::prelude::*; - -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"; +use std::collections::HashMap; pub struct AudioPlugin; impl Plugin for AudioPlugin { @@ -47,113 +32,109 @@ impl Plugin for AudioPlugin { #[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 { - IncomingChatMessage, + BGM, Click, + Connect, + Crash, + ElectricMotor, + EnterVehicle, + IncomingChatMessage, + Ion, + Ping, + Rocket, Switch, + Thruster, + WakeUp, Woosh, Zoom, - Ping, - Connect, - EnterVehicle, - Crash, - WakeUp, - None, +} + +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::Ping, + _ => Sfx::Click, + }; +} + +pub enum SfxType { + BGM, + LoopSfx, + OneOff, } #[derive(Event)] pub struct PlaySfxEvent(pub Sfx); #[derive(Event)] pub struct ToggleMusicEvent(); -#[derive(Component)] pub struct ComponentBGM; -#[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); -#[derive(Resource)] pub struct SoundClick(Handle); -#[derive(Resource)] pub struct SoundSwitch(Handle); -#[derive(Resource)] pub struct SoundWoosh(Handle); -#[derive(Resource)] pub struct SoundZoom(Handle); -#[derive(Resource)] pub struct SoundIncomingMessage(Handle); -#[derive(Resource)] pub struct SoundPing(Handle); -#[derive(Resource)] pub struct SoundConnect(Handle); -#[derive(Resource)] pub struct SoundBikeStart(Handle); -#[derive(Resource)] pub struct SoundCrash(Handle); -#[derive(Resource)] pub struct SoundWakeUp(Handle); +#[derive(Resource)] pub struct Sounds(HashMap>); pub fn setup( mut commands: Commands, settings: Res, asset_server: Res, ) { - commands.spawn(( - ComponentBGM, - AudioBundle { - source: SoundBGM(asset_server.load(ASSET_BGM)).0.clone(), - settings: PlaybackSettings { - mode: PlaybackMode::Loop, - paused: settings.mute_music, - ..default() + 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(( + *sfx, + AudioBundle { + source, + settings: PlaybackSettings { + mode: PlaybackMode::Loop, + paused: settings.mute_music, + ..default() + }, + }, + )); }, - }, - )); - commands.spawn(( - ComponentThrusterSound, - AudioBundle { - source: asset_server.load(ASSET_THRUSTER), - settings: PlaybackSettings { - mode: PlaybackMode::Loop, - volume: Volume::new(0.0), - paused: true, - ..default() + SfxType::LoopSfx => { + commands.spawn(( + *sfx, + AudioBundle { + source, + settings: PlaybackSettings { + mode: PlaybackMode::Loop, + volume: Volume::new(0.0), + paused: true, + ..default() + }, + }, + )); }, - }, - )); - commands.spawn(( - ComponentRocketSound, - AudioBundle { - source: asset_server.load(ASSET_ROCKET), - settings: PlaybackSettings { - mode: PlaybackMode::Loop, - volume: Volume::new(0.0), - paused: true, - ..default() - }, - }, - )); - commands.spawn(( - ComponentIonSound, - 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))); + SfxType::OneOff => () + } + } + commands.insert_resource(Sounds(map)); } pub fn toggle_bgm( @@ -178,67 +159,32 @@ pub fn play_sfx( mut commands: Commands, settings: Res, mut events_sfx: EventReader, - sound_click: Res, - sound_switch: Res, - sound_woosh: Res, - sound_zoom: Res, - sound_incoming_message: Res, - sound_ping: Res, - sound_connect: Res, - sound_bikestart: Res, - sound_crash: Res, - sound_wakeup: Res, + sounds: Res, ) { if settings.mute_sfx && !events_sfx.is_empty() { events_sfx.clear(); } for sfx in events_sfx.read() { - match sfx.0 { - Sfx::None => { continue; } - _ => {} + if let Some(source) = sounds.0.get(&sfx.0) { + commands.spawn(AudioBundle { + source: source.clone(), + settings: PlaybackSettings::DESPAWN, + }); } - commands.spawn(AudioBundle { - source: match sfx.0 { - 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, - }); } } -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( mut events: EventReader, - bgm_controller: Query<&AudioSink, With>, + q_audiosinks: Query<(&AudioSink, &Sfx)>, settings: Res, ) { if !events.is_empty() { 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 { bgm_sink.pause(); } diff --git a/src/camera.rs b/src/camera.rs index f6f296d..6b286b5 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -22,6 +22,7 @@ use bevy::transform::TransformSystem; use bevy_xpbd_3d::prelude::*; use bevy_xpbd_3d::plugins::sync; use crate::prelude::*; +use std::collections::HashMap; pub const INITIAL_ZOOM_LEVEL: f64 = 10.0; @@ -379,10 +380,7 @@ pub fn apply_input_to_player( windows: Query<&Window, With>, mut mouse_events: EventReader, key_input: Res>, - thruster_sound_controller: Query<&AudioSink, With>, - rocket_sound_controller: Query<&AudioSink, With>, - ion_sound_controller: Query<&AudioSink, With>, - electricmotor_sound_controller: Query<&AudioSink, With>, + q_audiosinks: Query<(&audio::Sfx, &AudioSink)>, q_target: Query<&LinearVelocity, (With, Without)>, mut q_playercam: Query<( &Transform, @@ -550,8 +548,13 @@ pub fn apply_input_to_player( } } + let mut sinks: HashMap = HashMap::new(); + for (sfx, sink) in &q_audiosinks { + sinks.insert(*sfx, sink); + } + // 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 speed = sink.speed(); 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![ - (1.2, actor::EngineType::Monopropellant, thruster_sound_controller.get_single()), - (1.0, actor::EngineType::Rocket, rocket_sound_controller.get_single()), - (1.4, actor::EngineType::Ion, ion_sound_controller.get_single()), + (1.2, actor::EngineType::Monopropellant, sinks.get(&audio::Sfx::Thruster)), + (1.0, actor::EngineType::Rocket, sinks.get(&audio::Sfx::Rocket)), + (1.4, actor::EngineType::Ion, sinks.get(&audio::Sfx::Ion)), ]; let seconds_to_max_vol = 0.05; let seconds_to_min_vol = 0.05; 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 { sink.pause(); }