diff --git a/README b/README new file mode 100644 index 0000000000000000000000000000000000000000..bf426b761f059effadb7d0864d8a206037bbb24a --- /dev/null +++ b/README @@ -0,0 +1,107 @@ +# Micro Bevy MusicBox + +Play some tunes + +## What? + +This library provides a convenience wrapper around bevy_kira_audio, handling all of the +setup for the common game audio scenario for you. + +There are 4 types of audio channel that will be added to your game, with crossfade tracks +for 2 of those; this means a total of 6 `AudioChannel` resources are created. + + * `Music` - The main music for your game (includes A/B for crossfading) + * `Ambient` - Any long and/or looping background ambience that you might want to layer on top of music (includes A/B for crossfading) + * `Sfx` - Any short sound effects + * `UI Sfx` - Any sound effects that specifically relate to the UI, allowing for more fine-grained control of audio levels + +Track volume is controlled by a resource, and is calculated as the individual track's volume settings multiplied by the master volume +setting + +## How? + +### Quickstart + +- Include the MusixBocPlugin plugin, or the CombinedAudioPlugins plugin group in your app +- Implement `SuppliesAudio` for a resource (or use the built in impl on `AssetServer`) +- Use `MusicBox<T: SuppliesAudio>` as a parameter on a system +- Call one of the `MusicBox::play_*` methods to play sounds + +``` +fn main() { + App::new() + .add_plugins(CombinedAudioPlugins) + .add_startup_system(|mut music_box: MusicBox<AssetServer>| { + music_box.play_music("music/bing_bong.mp3"); + }); +} +``` + +### In-Depth + +There is a plugin that just provides the layering on top of bevy_kira_audio if you are already integrating with it, +and a plugin group that will setup and configure bevy_kira_audio for you if not. Some bevy_ira_audio types are +re-exported, so you can depend solely on micro_bevy_musicbox if you don't have any advanced needs. + +```rust +use micro_bevy_musicbox::{CombinedAudioPlugins, MusicBoxPlugin}; + +// Either +fn main() { + App::new() + .add_plugin(MusicBoxPlugin); +} + +// Or +fn main() { + App::new() + .add_plugins(CombinedAudioPlugins); +} +``` + +In order to use the the MusicBox type, you will need to implement the `SuppliesAudio` trait on a resource. +This resource will need to be able to retrieve the requested audio track by name, although the specifics of +what that name represents will depend on how you implement the trait. + +Out of the box, there is a `SuppliesAudio` impl for `AssetServer`, allowing you to use resource paths. It is, +however, recommended that you create your own impl for your own resource type. + +```rust +/// An example storage resource that allows assets to be retrieved by name, +/// rather than by file path +pub struct AssetHandles { + // ...Other types... + pub sounds: HashMap<String, Handle<AudioSource>>, +} + +impl SuppliesAudio for AssetHandles { + fn get_audio_track<T: ToString>(&self, name: T) -> Option<Handle<AudioSource>> { + self.sounds.get(&name.to_string()).map(Handle::clone_weak) + } +} +``` + +Finally, you need to use the `MusicBox` type as a SystemParam, alongside your `SuppliesAudio` impl. +There is no binding of between MusicBox and SuppliesAudio, so you can use different impls in different +systems as you please, as long as the `SuppliesAudio` resource has been added to your world + +```rust +/// A simple event that causes a sound effect to be played. +/// N.B. In a real game, you probably just want to directly play a sound without events +pub struct PlaySoundEvent { + pub sound: String, +} + +// ...Register your event to your app... + +/// A system that reads PlaySoundEvent events and plays the sound effect, using the +/// previously created `AssetHandles` resource as a supplier +pub fn play_sounds( + mut events: EventReader<PlaySoundEvent>, + music_box: MusicBox<AssetHandles>, +) { + for PlaySoundEvent { sound } in events.iter() { + music_box.play_effect_once(sound); + } +} +``` \ No newline at end of file diff --git a/src/utilities.rs b/src/utilities.rs index 76f085a98404949d11febc549bab52272fe952bd..e41343106240795ce92bf0f05e73ba24e22abd31 100644 --- a/src/utilities.rs +++ b/src/utilities.rs @@ -82,3 +82,10 @@ impl<'w, 's, T: SuppliesAudio> MusicBox<'w, 's, T> { } } } + + +impl SuppliesAudio for AssetServer { + fn get_audio_track<T: ToString>(&self, name: T) -> Option<Handle<AudioSource>> { + Some(self.load(&name.to_string())) + } +} \ No newline at end of file