Added crickets blocktype, added 3 new cricket sounds, made crickets chirp consistently, made frogs more sporadic

This commit is contained in:
DaforLynx 2021-02-12 00:54:42 +00:00 committed by Justin Shipsey
parent 44a9d8dc71
commit ebbb06a400
9 changed files with 130 additions and 24 deletions

View File

@ -28,11 +28,24 @@
], ],
threshold: 14.0, threshold: 14.0,
), ),
Cricket: ( //Crickets: -20dB
Cricket1: (
files: [ files: [
"voxygen.audio.sfx.ambient.crickets_1", "voxygen.audio.sfx.ambient.crickets_1",
], ],
threshold: 1.0, threshold: 0.0,
),
Cricket2: (
files: [
"voxygen.audio.sfx.ambient.crickets_2",
],
threshold: 0.0,
),
Cricket3: (
files: [
"voxygen.audio.sfx.ambient.crickets_3",
],
threshold: 0.0,
), ),
Frog: ( Frog: (
files: [ files: [

Binary file not shown.

BIN
assets/voxygen/audio/sfx/ambient/crickets_2.wav (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/audio/sfx/ambient/crickets_3.wav (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -59,6 +59,7 @@ pub struct TerrainChunkMeta {
tree_density: f32, tree_density: f32,
contains_cave: bool, contains_cave: bool,
contains_river: bool, contains_river: bool,
temp: f32,
} }
impl TerrainChunkMeta { impl TerrainChunkMeta {
@ -69,6 +70,7 @@ impl TerrainChunkMeta {
tree_density: f32, tree_density: f32,
contains_cave: bool, contains_cave: bool,
contains_river: bool, contains_river: bool,
temp: f32,
) -> Self { ) -> Self {
Self { Self {
name, name,
@ -77,6 +79,7 @@ impl TerrainChunkMeta {
tree_density, tree_density,
contains_cave, contains_cave,
contains_river, contains_river,
temp,
} }
} }
@ -88,6 +91,7 @@ impl TerrainChunkMeta {
tree_density: 0.0, tree_density: 0.0,
contains_cave: false, contains_cave: false,
contains_river: false, contains_river: false,
temp: 0.0,
} }
} }
@ -102,6 +106,8 @@ impl TerrainChunkMeta {
pub fn contains_cave(&self) -> bool { self.contains_cave } pub fn contains_cave(&self) -> bool { self.contains_cave }
pub fn contains_river(&self) -> bool { self.contains_river } pub fn contains_river(&self) -> bool { self.contains_river }
pub fn temp(&self) -> f32 { self.temp }
} }
// Terrain type aliases // Terrain type aliases

View File

@ -17,7 +17,7 @@ use common::{
use common_sys::state::State; use common_sys::state::State;
use hashbrown::HashMap; use hashbrown::HashMap;
use rand::{thread_rng, Rng}; use rand::{thread_rng, Rng};
use std::time::Instant; use std::time::{Duration, Instant};
use vek::*; use vek::*;
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
@ -30,7 +30,9 @@ impl Default for PreviousBlockState {
fn default() -> Self { fn default() -> Self {
Self { Self {
event: SfxEvent::Idle, event: SfxEvent::Idle,
time: Instant::now(), time: Instant::now()
.checked_add(Duration::from_millis(thread_rng().gen_range(0..500)))
.unwrap_or_else(Instant::now),
} }
} }
} }
@ -61,10 +63,10 @@ impl EventMapper for BlockEventMapper {
(e.floor() as i32).div_euclid(sz as i32) (e.floor() as i32).div_euclid(sz as i32)
}); });
// For determining if underground // For determining if underground/crickets should chirp
let terrain_alt = match client.current_chunk() { let (terrain_alt, temp) = match client.current_chunk() {
Some(chunk) => chunk.meta().alt(), Some(chunk) => (chunk.meta().alt(), chunk.meta().temp()),
None => 0.0, None => (0.0, 0.0),
}; };
struct BlockSounds<'a> { struct BlockSounds<'a> {
@ -112,7 +114,7 @@ impl EventMapper for BlockEventMapper {
// //cond: |st| st.get_day_period().is_dark(), // //cond: |st| st.get_day_period().is_dark(),
//}, //},
BlockSounds { BlockSounds {
blocks: |boi| &boi.reeds, blocks: |boi| &boi.frogs,
range: 1, range: 1,
sfx: SfxEvent::Frog, sfx: SfxEvent::Frog,
volume: 0.8, volume: 0.8,
@ -126,10 +128,24 @@ impl EventMapper for BlockEventMapper {
// cond: |st| st.get_day_period().is_dark(), // cond: |st| st.get_day_period().is_dark(),
//}, //},
BlockSounds { BlockSounds {
blocks: |boi| &boi.grass, blocks: |boi| &boi.cricket1,
range: 1, range: 1,
sfx: SfxEvent::Cricket, sfx: SfxEvent::Cricket1,
volume: 0.5, volume: 0.33,
cond: |st| st.get_day_period().is_dark(),
},
BlockSounds {
blocks: |boi| &boi.cricket2,
range: 1,
sfx: SfxEvent::Cricket2,
volume: 0.33,
cond: |st| st.get_day_period().is_dark(),
},
BlockSounds {
blocks: |boi| &boi.cricket3,
range: 1,
sfx: SfxEvent::Cricket3,
volume: 0.33,
cond: |st| st.get_day_period().is_dark(), cond: |st| st.get_day_period().is_dark(),
}, },
BlockSounds { BlockSounds {
@ -145,12 +161,12 @@ impl EventMapper for BlockEventMapper {
for sounds in sounds.iter() { for sounds in sounds.iter() {
// If the timing condition is false, continue // If the timing condition is false, continue
// or if the player is far enough underground, continue // or if the player is far enough underground, continue
// TODO Address bird hack properly. See TODO on line 171 // TODO Address bird hack properly. See TODO on line 190
if !(sounds.cond)(state) if !(sounds.cond)(state)
|| player_pos.0.z < (terrain_alt - 30.0) || player_pos.0.z < (terrain_alt - 30.0)
|| (sounds.sfx == SfxEvent::Birdcall && thread_rng().gen_bool(0.995)) || (sounds.sfx == SfxEvent::Birdcall && thread_rng().gen_bool(0.995))
|| (sounds.sfx == SfxEvent::Owl && thread_rng().gen_bool(0.998)) || (sounds.sfx == SfxEvent::Owl && thread_rng().gen_bool(0.998))
|| (sounds.sfx == SfxEvent::Cricket && thread_rng().gen_bool(0.99)) || (sounds.sfx == SfxEvent::Frog && thread_rng().gen_bool(0.9))
{ {
continue; continue;
} }
@ -172,9 +188,9 @@ impl EventMapper for BlockEventMapper {
// TODO Address this hack properly, potentially by making a new // TODO Address this hack properly, potentially by making a new
// block of interest type which picks fewer leaf blocks // block of interest type which picks fewer leaf blocks
// Hack to reduce the number of bird sounds (too many leaf blocks) // Hack to reduce the number of bird sounds (too many leaf blocks)
if (sounds.sfx == SfxEvent::Birdcall || sounds.sfx == SfxEvent::Owl) if ((sounds.sfx == SfxEvent::Birdcall || sounds.sfx == SfxEvent::Owl)
&& thread_rng().gen_bool(0.999) && thread_rng().gen_bool(0.999))
|| (sounds.sfx == SfxEvent::Cricket && thread_rng().gen_bool(0.999)) || (sounds.sfx == SfxEvent::Frog && thread_rng().gen_bool(0.75))
{ {
continue; continue;
} }
@ -183,7 +199,11 @@ impl EventMapper for BlockEventMapper {
let block_pos = block_pos.map(|x| x as f32); let block_pos = block_pos.map(|x| x as f32);
if Self::should_emit(internal_state, triggers.get_key_value(&sounds.sfx)) { if Self::should_emit(
internal_state,
triggers.get_key_value(&sounds.sfx),
temp,
) {
// If the camera is within SFX distance // If the camera is within SFX distance
if (block_pos.distance_squared(cam_pos)) < SFX_DIST_LIMIT_SQR { if (block_pos.distance_squared(cam_pos)) < SFX_DIST_LIMIT_SQR {
let underwater = state let underwater = state
@ -228,12 +248,42 @@ impl BlockEventMapper {
fn should_emit( fn should_emit(
previous_state: &PreviousBlockState, previous_state: &PreviousBlockState,
sfx_trigger_item: Option<(&SfxEvent, &SfxTriggerItem)>, sfx_trigger_item: Option<(&SfxEvent, &SfxTriggerItem)>,
temp: f32,
) -> bool { ) -> bool {
if let Some((event, item)) = sfx_trigger_item { if let Some((event, item)) = sfx_trigger_item {
//The interval between cricket chirps calculated by converting chunk
// temperature to centigrade (we should create a function for this) and applying
// the "cricket formula" to it
let cricket_interval = (25.0 / (3.0 * ((temp * 30.0) + 15.0))).max(0.5);
if &previous_state.event == event { if &previous_state.event == event {
//In case certain sounds need modification to their threshold, //In case certain sounds need modification to their threshold,
//use match event //use match event
previous_state.time.elapsed().as_secs_f32() >= item.threshold match event {
//Crickets' threshold is 0.0 by default
SfxEvent::Cricket1 => {
previous_state.time.elapsed().as_secs_f32()
>= cricket_interval + thread_rng().gen_range(-0.1..0.1)
},
SfxEvent::Cricket2 => {
//the length and manner of this sound is quite different
if cricket_interval < 0.75 {
previous_state.time.elapsed().as_secs_f32() >= 0.75
} else {
previous_state.time.elapsed().as_secs_f32()
>= cricket_interval + thread_rng().gen_range(-0.1..0.1)
}
},
SfxEvent::Cricket3 => {
previous_state.time.elapsed().as_secs_f32()
>= cricket_interval + thread_rng().gen_range(-0.1..0.1)
},
//Adds random factor to frogs
SfxEvent::Frog => {
previous_state.time.elapsed().as_secs_f32()
>= thread_rng().gen_range(-2.0..2.0)
},
_ => previous_state.time.elapsed().as_secs_f32() >= item.threshold,
}
} else { } else {
true true
} }

View File

@ -141,7 +141,9 @@ pub enum SfxEvent {
Embers, Embers,
Birdcall, Birdcall,
Owl, Owl,
Cricket, Cricket1,
Cricket2,
Cricket3,
Frog, Frog,
Bees, Bees,
RunningWater, RunningWater,

View File

@ -18,6 +18,11 @@ pub struct BlocksOfInterest {
pub flowers: Vec<Vec3<i32>>, pub flowers: Vec<Vec3<i32>>,
pub fire_bowls: Vec<Vec3<i32>>, pub fire_bowls: Vec<Vec3<i32>>,
pub snow: Vec<Vec3<i32>>, pub snow: Vec<Vec3<i32>>,
//This is so crickets stay in place and don't randomly change sounds
pub cricket1: Vec<Vec3<i32>>,
pub cricket2: Vec<Vec3<i32>>,
pub cricket3: Vec<Vec3<i32>>,
pub frogs: Vec<Vec3<i32>>,
// Note: these are only needed for chunks within the iteraction range so this is a potential // Note: these are only needed for chunks within the iteraction range so this is a potential
// area for optimization // area for optimization
pub interactables: Vec<Vec3<i32>>, pub interactables: Vec<Vec3<i32>>,
@ -39,6 +44,10 @@ impl BlocksOfInterest {
let mut lights = Vec::new(); let mut lights = Vec::new();
let mut fire_bowls = Vec::new(); let mut fire_bowls = Vec::new();
let mut snow = Vec::new(); let mut snow = Vec::new();
let mut cricket1 = Vec::new();
let mut cricket2 = Vec::new();
let mut cricket3 = Vec::new();
let mut frogs = Vec::new();
chunk chunk
.vol_iter( .vol_iter(
@ -52,7 +61,17 @@ impl BlocksOfInterest {
.for_each(|(pos, block)| { .for_each(|(pos, block)| {
match block.kind() { match block.kind() {
BlockKind::Leaves if thread_rng().gen_range(0..16) == 0 => leaves.push(pos), BlockKind::Leaves if thread_rng().gen_range(0..16) == 0 => leaves.push(pos),
BlockKind::Grass if thread_rng().gen_range(0..16) == 0 => grass.push(pos), BlockKind::Grass => {
if thread_rng().gen_range(0..16) == 0 {
grass.push(pos);
}
match thread_rng().gen_range(0..8192) {
1 => cricket1.push(pos),
2 => cricket2.push(pos),
3 => cricket3.push(pos),
_ => {},
}
},
BlockKind::Water BlockKind::Water
if chunk.meta().contains_river() && thread_rng().gen_range(0..16) == 0 => if chunk.meta().contains_river() && thread_rng().gen_range(0..16) == 0 =>
{ {
@ -73,7 +92,12 @@ impl BlocksOfInterest {
}, },
Some(SpriteKind::WallSconce) => fire_bowls.push(pos + Vec3::unit_z()), Some(SpriteKind::WallSconce) => fire_bowls.push(pos + Vec3::unit_z()),
Some(SpriteKind::Beehive) => beehives.push(pos), Some(SpriteKind::Beehive) => beehives.push(pos),
Some(SpriteKind::Reed) => reeds.push(pos), Some(SpriteKind::Reed) => {
reeds.push(pos);
if thread_rng().gen_range(0..12) == 0 {
frogs.push(pos)
}
},
Some(SpriteKind::PinkFlower) => flowers.push(pos), Some(SpriteKind::PinkFlower) => flowers.push(pos),
Some(SpriteKind::PurpleFlower) => flowers.push(pos), Some(SpriteKind::PurpleFlower) => flowers.push(pos),
Some(SpriteKind::RedFlower) => flowers.push(pos), Some(SpriteKind::RedFlower) => flowers.push(pos),
@ -104,6 +128,10 @@ impl BlocksOfInterest {
lights, lights,
fire_bowls, fire_bowls,
snow, snow,
cricket1,
cricket2,
cricket3,
frogs,
} }
} }
} }

View File

@ -226,6 +226,7 @@ impl World {
sim_chunk.tree_density, sim_chunk.tree_density,
sim_chunk.cave.1.alt != 0.0, sim_chunk.cave.1.alt != 0.0,
sim_chunk.river.is_river(), sim_chunk.river.is_river(),
sim_chunk.temp,
); );
let mut chunk = TerrainChunk::new(base_z, stone, air, meta); let mut chunk = TerrainChunk::new(base_z, stone, air, meta);