blackout/src/sound/footstep.rs

83 lines
2.6 KiB
Rust
Raw Normal View History

use std::collections::HashMap;
2022-08-03 14:43:07 +00:00
use bevy::{prelude::*, transform::TransformSystem};
use bevy_synthizer::{Audio, Sound};
use rand::random;
2023-04-01 12:20:59 +00:00
use crate::core::PointLike;
#[derive(Component, Clone, Debug)]
pub struct Footstep {
pub audio: Audio,
pub step_length: f32,
2022-05-23 18:35:25 +00:00
pub gain: f64,
pub pitch: Option<f64>,
pub pitch_variation: Option<f64>,
}
impl Default for Footstep {
fn default() -> Self {
Self {
audio: default(),
step_length: 0.8,
gain: 1.,
2022-05-23 18:35:25 +00:00
pitch: None,
pitch_variation: Some(0.15),
}
}
}
2022-08-03 14:43:07 +00:00
fn added(mut commands: Commands, footsteps: Query<(Entity, &Footstep), Added<Footstep>>) {
2023-03-28 17:13:23 +00:00
for (entity, footstep) in &footsteps {
let buffer = footstep.audio.clone();
2023-04-01 12:20:59 +00:00
commands.entity(entity).insert(Sound {
audio: buffer.into(),
paused: true,
..default()
});
}
}
fn update(
mut last_step_distance: Local<HashMap<Entity, (f32, GlobalTransform)>>,
mut footsteps: Query<(Entity, &Footstep, &Parent, &mut Sound)>,
transforms_storage: Query<&GlobalTransform>,
) {
2023-03-28 17:13:23 +00:00
for (entity, footstep, parent, mut sound) in &mut footsteps {
if let Ok(transform) = transforms_storage.get(**parent) {
if let Some(last) = last_step_distance.get(&entity) {
let distance = last.0 + (last.1.distance(transform));
if distance >= footstep.step_length {
last_step_distance.insert(entity, (0., *transform));
sound.gain = footstep.gain;
sound.pitch = footstep.pitch.unwrap_or(1.);
if let Some(pitch_variation) = footstep.pitch_variation {
let mut pitch = sound.pitch - pitch_variation / 2.;
pitch += random::<f64>() * pitch_variation;
sound.pitch = pitch;
2022-05-23 18:35:25 +00:00
}
sound.paused = false;
sound.restart = true;
} else if last.1 != *transform {
last_step_distance.insert(entity, (distance, *transform));
}
} else {
last_step_distance.insert(entity, (0., *transform));
}
}
}
}
pub struct FootstepPlugin;
impl Plugin for FootstepPlugin {
fn build(&self, app: &mut App) {
app.add_system(added.in_base_set(CoreSet::PreUpdate))
2023-03-28 16:57:37 +00:00
.add_system(
update
.after(TransformSystem::TransformPropagate)
.in_base_set(CoreSet::PostUpdate),
);
}
}