Inspirateur / riverbed

A Minecraft-inspired Bevy game
MIT License
17 stars 0 forks source link

Audio / Music #13

Open nerdachse opened 2 months ago

nerdachse commented 2 months ago

Hey!

Adding some audio goes a long way for immersion.

There is multiple facets to this.

Although bevy's audio story isn't great at the moment I've looked into a simple way to incorporate them into riverbed (and other projects)

E.g. for footsteps a simple system could look like this:

pub struct AudioPlugin;

impl Plugin for AudioPlugin {
    fn build(&self, app: &mut bevy::prelude::App) {
        app.add_systems(Update, footsteps);
    }
}

fn footsteps(
    mut footsteps: Local<Option<Entity>>,
    mut last_pos: Local<GlobalTransform>,
    mut cmd: Commands,
    ass: Res<AssetServer>,
    q_realm: Query<&Realm, With<PlayerControlled>>,
    q_player: Query<&GlobalTransform, With<FpsCam>>,
    q_playback: Query<&PlaybackSettings>,
    world: Res<Blocks>,
) {
    let Ok(realm) = q_realm.get_single() else {
        bevy::log::warn!("no realm");
        return;
    };
    let Ok(transform) = q_player.get_single() else {
        bevy::log::warn!("no player camera");
        return;
    };
    let Some(below) = world.raycast(*realm, transform.translation(), transform.down(), 2.0) else {
        bevy::log::debug!("nothing below!");
        return;
    };

    if last_pos.translation() == transform.translation() {
        return;
    }
    *last_pos = transform.clone();

    let entity = *footsteps.get_or_insert(cmd.spawn_empty().id());
    if q_playback.get(entity).is_ok() {
        bevy::log::warn!("Still playing a sound");
        return;
    }

    let Some(source) = (match world.get_block_safe(below.pos) {
        Block::GrassBlock => {
            let mut rng = rand::thread_rng();
            let random_number = rng.gen_range(1..=4);
            Some(format!(
                "sounds/Footsteps Sound FX Pack/OGG/Footsteps_Grass_{:02}.ogg",
                random_number
            ))
        }
        Block::Dirt => {
            let mut rng = rand::thread_rng();
            let random_number = rng.gen_range(1..=4);
            Some(format!(
                "sounds/Footsteps Sound FX Pack/OGG/Footsteps_Dirt_{:02}.ogg",
                random_number
            ))
        }
        Block::Air => None,
        other => {
            bevy::log::warn!("Footsteps for {other:?} not implemented");
            None
        }
    }) else {
        return;
    };

    cmd.entity(entity).insert(AudioBundle {
        source: ass.load(source),
        settings: PlaybackSettings {
            // After the sound has played, this component will be removed
            mode: PlaybackMode::Remove,
            ..default()
        },
    });
}

If you're interested in this, I am open to give back - the main point is just that we have to find assets that we can bundle. I bought some on itch.io for personal use.

Anyway, what do you think? ~ Tom

Inspirateur commented 2 months ago

Thanks for this, it's a good start :)

Here are some thoughts:

Inspirateur commented 1 week ago

I'm realizing there's already 3d sound support in bevy. Cool! https://bevyengine.org/examples/audio/spatial-audio-3d/

Inspirateur commented 1 week ago

Just added (horrendous) sounds for:

As well as the code necessary to play them!

Ambient sounds and music (which might be the same thing in riverbed) will come later I think :p