mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Wind transition smoothing
This commit is contained in:
parent
f182002e38
commit
2d088faea4
@ -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() }
|
||||
|
@ -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");
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user