veebee 1.1.1

A Simple Rust Game Engine For 2D
Documentation
use crate::prelude::GameState;
use bevy::prelude::*;
use bevy_kira_audio::{Audio, AudioChannel};
use std::array::IntoIter;

#[derive(Debug, Default)]
pub struct AudioManager {
    sfx_queue: Vec<SfxPreset>,
    music_queue: Vec<Option<(MusicPreset, f32)>>,
    playing: AudioChannel,
}

impl AudioManager {

    pub fn play_sfx(&mut self, sfx_preset: SfxPreset) {
        self.sfx_queue.push(sfx_preset);
    }
    pub fn play_music(&mut self, music_preset: MusicPreset, volume: f32) {
        self.music_queue
            .push(Some((music_preset, volume.clamp(0.0, 1.0))));
    }

    pub fn stop_music(&mut self) {
        self.music_queue.push(None);
    }
}

#[derive(Default)]
pub struct AudioManagerPlugin;

impl Plugin for AudioManagerPlugin {
    fn build(&self, app: &mut bevy::prelude::AppBuilder) {
        app.add_system(queue_managed_audio_system.system());
    }
}

#[derive(Copy, Clone, Debug)]
pub enum SfxPreset {
    Click,
    Confirmation1,
    Confirmation2,
    Congratulations,
    Forcefield1,
    Forcefield2,
    Impact1,
    Impact2,
    Impact3,
    Jingle1,
    Jingle2,
    Jingle3,
    Minimize1,
    Minimize2,
    Switch1,
    Switch2,
    Tones1,
    Tones2,
}

impl SfxPreset {
    fn to_path(self) -> &'static str {
        match self {
            SfxPreset::Click => "audio/sfx/click.ogg",
            SfxPreset::Confirmation1 => "audio/sfx/confirmation1.ogg",
            SfxPreset::Confirmation2 => "audio/sfx/confirmation2.ogg",
            SfxPreset::Congratulations => "audio/sfx/congratulations.ogg",
            SfxPreset::Forcefield1 => "audio/sfx/forcefield1.ogg",
            SfxPreset::Forcefield2 => "audio/sfx/forcefield2.ogg",
            SfxPreset::Impact1 => "audio/sfx/impact1.ogg",
            SfxPreset::Impact2 => "audio/sfx/impact2.ogg",
            SfxPreset::Impact3 => "audio/sfx/impact3.ogg",
            SfxPreset::Jingle1 => "audio/sfx/jingle1.ogg",
            SfxPreset::Jingle2 => "audio/sfx/jingle2.ogg",
            SfxPreset::Jingle3 => "audio/sfx/jingle3.ogg",
            SfxPreset::Minimize1 => "audio/sfx/minimize1.ogg",
            SfxPreset::Minimize2 => "audio/sfx/minimize2.ogg",
            SfxPreset::Switch1 => "audio/sfx/switch1.ogg",
            SfxPreset::Switch2 => "audio/sfx/switch2.ogg",
            SfxPreset::Tones1 => "audio/sfx/tones1.ogg",
            SfxPreset::Tones2 => "audio/sfx/tones2.ogg",
        }
    }

    pub fn variant_iter() -> IntoIter<SfxPreset, 18> {
        static SFX_PRESETS: [SfxPreset; 18] = [
            SfxPreset::Click,
            SfxPreset::Confirmation1,
            SfxPreset::Confirmation2,
            SfxPreset::Congratulations,
            SfxPreset::Forcefield1,
            SfxPreset::Forcefield2,
            SfxPreset::Impact1,
            SfxPreset::Impact2,
            SfxPreset::Impact3,
            SfxPreset::Jingle1,
            SfxPreset::Jingle2,
            SfxPreset::Jingle3,
            SfxPreset::Minimize1,
            SfxPreset::Minimize2,
            SfxPreset::Switch1,
            SfxPreset::Switch2,
            SfxPreset::Tones1,
            SfxPreset::Tones2,
        ];
        IntoIter::new(SFX_PRESETS)
    }
}

#[derive(Copy, Clone, Debug)]
pub enum MusicPreset {
    Classy8Bit,
    MysteriousMagic,
    WhimsicalPopsicle,
}

impl MusicPreset {
    fn to_path(self) -> &'static str {
        match self {
            MusicPreset::Classy8Bit => "audio/music/Classy 8-Bit.oga",
            MusicPreset::MysteriousMagic => "audio/music/Mysterious Magic.oga",
            MusicPreset::WhimsicalPopsicle => "audio/music/Whimsical Popsicle.oga",
        }
    }

    pub fn variant_iter() -> IntoIter<MusicPreset, 3> {
        static MUSIC_PRESETS: [MusicPreset; 3] = [
            MusicPreset::Classy8Bit,
            MusicPreset::MysteriousMagic,
            MusicPreset::WhimsicalPopsicle,
        ];
        IntoIter::new(MUSIC_PRESETS)
    }
}

pub fn queue_managed_audio_system(
    asset_server: Res<AssetServer>,
    audio: Res<Audio>,
    mut game_state: ResMut<GameState>,
) {
    for sfx in game_state.audio_manager.sfx_queue.drain(..) {
        let sfx_handle = asset_server.load(sfx.to_path());
        audio.play(sfx_handle);
    }
    let playing = game_state.audio_manager.playing.clone();
    let mut new_playing = playing.clone();
    for item in game_state.audio_manager.music_queue.drain(..) {
        audio.stop_channel(&playing);
        if let Some((music, volume)) = item {
            let music_path = music.to_path();
            let music_handle = asset_server.load(music_path);
            new_playing = AudioChannel::new(music_path.into());
            audio.set_volume_in_channel(volume, &new_playing);
            audio.play_looped_in_channel(music_handle, &new_playing);
        }
    }
    game_state.audio_manager.playing = new_playing;
}