Wind transition smoothing

This commit is contained in:
jiminycrick 2020-11-07 21:26:20 -08:00
parent f182002e38
commit 2d088faea4
5 changed files with 78 additions and 76 deletions

View File

@ -21,7 +21,6 @@ use crate::audio::{
Listener,
};
use rodio::{OutputStreamHandle, Sample, Sink, Source, SpatialSink};
use std::time::Duration;
use vek::*;
#[derive(PartialEq, Clone, Copy)]
@ -148,6 +147,8 @@ pub struct WindChannel {
impl WindChannel {
pub fn set_volume(&mut self, volume: f32) { self.sink.set_volume(volume); }
pub fn volume(&mut self) -> f32 { self.sink.volume() }
pub fn new(stream: &OutputStreamHandle) -> Self {
Self {
sink: Sink::try_new(stream).unwrap(),
@ -203,18 +204,6 @@ impl SfxChannel {
self.sink.append(source);
}
pub fn play_with_reverb<S: rodio::Source>(&mut self, source: S)
where
S: Sized + Send + 'static,
<S as Iterator>::Item: Sample,
<S as Iterator>::Item: Sync,
<S as Iterator>::Item: Send,
<S as std::iter::Iterator>::Item: std::fmt::Debug,
{
let source = source.buffered().reverb(Duration::from_millis(200), 0.2);
self.sink.append(source);
}
pub fn set_volume(&mut self, volume: f32) { self.sink.set_volume(volume); }
pub fn is_done(&self) -> bool { self.sink.empty() }

View File

@ -212,24 +212,6 @@ impl AudioFrontend {
}
}
/// Play (once) an sfx file by file path at the give position and volume
/// but with reverb
pub fn play_reverb_sfx(&mut self, sound: &str, pos: Vec3<f32>, vol: Option<f32>) {
if self.audio_stream.is_some() {
let sound = self
.sound_cache
.load_sound(sound)
.amplify(vol.unwrap_or(1.0));
let listener = self.listener.clone();
if let Some(channel) = self.get_sfx_channel() {
channel.set_pos(pos);
channel.update(&listener);
channel.play_with_reverb(sound);
}
}
}
fn play_wind(&mut self, sound: &str, volume_multiplier: f32) {
if self.audio_stream.is_some() {
if let Some(channel) = self.get_wind_channel(volume_multiplier) {
@ -261,6 +243,18 @@ impl AudioFrontend {
}
}
fn get_wind_volume(&mut self) -> f32 {
if self.audio_stream.is_some() {
if let Some(channel) = self.wind_channels.iter_mut().find(|_c| true) {
channel.volume() / self.sfx_volume
} else {
0.0
}
} else {
0.0
}
}
fn play_music(&mut self, sound: &str, channel_tag: MusicChannelTag) {
if let Some(channel) = self.get_music_channel(channel_tag) {
let file = assets::load_file(&sound, &["ogg"]).expect("Failed to load sound");

View File

@ -114,7 +114,7 @@ impl EventMapper for MovementEventMapper {
// it was dispatched
internal_state.event = mapped_event;
internal_state.on_ground = physics.on_ground;
if physics.in_fluid.is_some() {
if physics.in_liquid.is_some() {
internal_state.in_water = true;
} else {
internal_state.in_water = false;
@ -182,8 +182,8 @@ impl MovementEventMapper {
underfoot_block_kind: BlockKind,
) -> SfxEvent {
// Match run / roll / swim state
if physics_state.in_fluid.is_some() && vel.magnitude() > 0.1
|| !previous_state.in_water && physics_state.in_fluid.is_some()
if physics_state.in_liquid.is_some() && vel.magnitude() > 0.1
|| !previous_state.in_water && physics_state.in_liquid.is_some()
{
return SfxEvent::Swim;
} else if physics_state.on_ground && vel.magnitude() > 0.1
@ -222,7 +222,7 @@ impl MovementEventMapper {
vel: Vec3<f32>,
underfoot_block_kind: BlockKind,
) -> SfxEvent {
if physics_state.in_fluid.is_some() && vel.magnitude() > 0.1 {
if physics_state.in_liquid.is_some() && vel.magnitude() > 0.1 {
return SfxEvent::Swim;
} else if physics_state.on_ground && vel.magnitude() > 0.1 {
match underfoot_block_kind {

View File

@ -254,10 +254,6 @@ impl SfxMgr {
let ecs = state.ecs();
let focus_off = camera.get_focus_pos().map(f32::trunc);
let cave = match client.current_chunk() {
Some(chunk) => chunk.meta().cave_alt() != 0.0,
None => false,
};
let underwater = state
.terrain()
.get((camera.dependents().cam_pos + focus_off).map(|e| e.floor() as i32))
@ -305,9 +301,6 @@ impl SfxMgr {
if underwater {
audio.play_underwater_sfx(sfx_file, position, event.vol);
} else if cave {
println!("Reverbbbbbbbbbb");
audio.play_reverb_sfx(sfx_file, position, event.vol);
} else {
audio.play_sfx(sfx_file, position, event.vol);
}

View File

@ -2,13 +2,13 @@
use crate::{audio::AudioFrontend, scene::Camera};
use client::Client;
use common::{assets, state::State, terrain::BlockKind, vol::ReadVol};
use rand::{prelude::SliceRandom, thread_rng, Rng};
use serde::Deserialize;
use std::time::Instant;
use tracing::warn;
const DAY_START_SECONDS: u32 = 28800; // 8:00
const DAY_END_SECONDS: u32 = 70200; // 19:30
// For if we want wind to vary strength by time of day
//const DAY_START_SECONDS: u32 = 28800; // 8:00
//const DAY_END_SECONDS: u32 = 70200; // 19:30
#[derive(Debug, Default, Deserialize)]
struct WindCollection {
@ -21,32 +21,25 @@ pub struct WindItem {
path: String,
/// Length of the track in seconds
length: f32,
/// Whether this track should play during day or night
timing: Option<DayPeriod>,
/* Whether this track should play during day or night
* timing: Option<DayPeriod>, */
}
/// Allows control over when a track should play based on in-game time of day
#[derive(Debug, Deserialize, PartialEq)]
enum DayPeriod {
/// 8:00 AM to 7:30 PM
Day,
/// 7:31 PM to 6:59 AM
Night,
}
/// Determines whether the sound is stopped, playing, or fading
#[derive(Debug, Deserialize, PartialEq)]
enum PlayState {
Playing,
Stopped,
FadingOut,
FadingIn,
}
///// Allows control over when a track should play based on in-game time of day
//#[derive(Debug, Deserialize, PartialEq)]
//enum DayPeriod {
// /// 8:00 AM to 7:30 PM
// Day,
// /// 7:31 PM to 6:59 AM
// Night,
//}
pub struct WindMgr {
soundtrack: WindCollection,
began_playing: Instant,
next_track_change: f32,
volume: f32,
tree_multiplier: f32,
}
impl WindMgr {
@ -56,6 +49,8 @@ impl WindMgr {
soundtrack: Self::load_soundtrack_items(),
began_playing: Instant::now(),
next_track_change: 0.0,
volume: 0.0,
tree_multiplier: 0.0,
}
}
@ -69,9 +64,27 @@ impl WindMgr {
camera: &Camera,
) {
if audio.sfx_enabled() && !self.soundtrack.tracks.is_empty() {
let alt_multiplier = ((Self::get_current_alt(client) - 250.0) / 1200.0).abs();
let tree_multiplier = 1.0 - Self::get_current_tree_density(client);
let mut volume_multiplier = alt_multiplier * tree_multiplier;
let player_alt = Self::get_current_alt(client);
let terrain_alt = Self::get_current_terrain_alt(client);
let alt_multiplier = (player_alt / 1200.0).abs();
let mut tree_multiplier = self.tree_multiplier;
let new_tree_multiplier = if (player_alt - terrain_alt) < 150.0 {
1.0 - Self::get_current_tree_density(client)
} else {
1.0
};
if tree_multiplier < new_tree_multiplier {
tree_multiplier += 0.001;
} else if tree_multiplier > new_tree_multiplier {
tree_multiplier -= 0.001;
}
self.tree_multiplier = tree_multiplier;
println!("tree multiplier: {}", tree_multiplier);
let mut volume_multiplier = alt_multiplier * self.tree_multiplier;
let focus_off = camera.get_focus_pos().map(f32::trunc);
let cam_pos = camera.dependents().cam_pos + focus_off;
@ -86,11 +99,24 @@ impl WindMgr {
{
volume_multiplier = volume_multiplier * 0.1;
}
if cam_pos.z < Self::get_current_terrain_alt(client) {
if cam_pos.z < Self::get_current_terrain_alt(client) - 20.0 {
volume_multiplier = 0.0;
}
audio.set_wind_volume(volume_multiplier);
if volume_multiplier > 1.0 {
volume_multiplier = 1.0
}
let target_volume = volume_multiplier;
println!("target vol: {}", volume_multiplier);
println!("current_wind_volume: {}", self.volume);
self.volume = audio.get_wind_volume();
if self.volume < target_volume {
audio.set_wind_volume(self.volume + 0.001);
} else if self.volume > target_volume {
audio.set_wind_volume(self.volume - 0.001);
}
if self.began_playing.elapsed().as_secs_f32() > self.next_track_change {
//let game_time = (state.get_time_of_day() as u64 % 86400) as u32;
@ -105,13 +131,13 @@ impl WindMgr {
}
}
fn get_current_day_period(game_time: u32) -> DayPeriod {
if game_time > DAY_START_SECONDS && game_time < DAY_END_SECONDS {
DayPeriod::Day
} else {
DayPeriod::Night
}
}
//fn get_current_day_period(game_time: u32) -> DayPeriod {
// if game_time > DAY_START_SECONDS && game_time < DAY_END_SECONDS {
// DayPeriod::Day
// } else {
// DayPeriod::Night
// }
//}
fn get_current_alt(client: &Client) -> f32 {
match client.current_position() {