A few more audio tweaks.

This commit is contained in:
Storm Dragon
2026-01-20 02:47:10 -05:00
parent 385ed3fd9b
commit 9b7fbc8266
6 changed files with 113 additions and 18 deletions

View File

@@ -16,6 +16,7 @@ sound_pool p(100);
#include "src/base_system.nvgt"
#include "src/time_system.nvgt"
#include "src/audio_utils.nvgt"
#include "src/creature_audio.nvgt"
#include "src/notify.nvgt"
int run_main_menu() {

View File

@@ -42,9 +42,9 @@ void perform_spear_attack(int current_x) {
p.play_stationary("sounds/weapons/spear_hit.ogg", false);
// Play hit sound based on enemy type (both use same hit sound for now)
if (get_bandit_at(hit_pos) != null) {
play_1d_with_volume_step("sounds/enemies/zombie_hit.ogg", x, hit_pos, false, BANDIT_SOUND_VOLUME_STEP);
play_creature_hit_sound("sounds/enemies/zombie_hit.ogg", x, hit_pos, BANDIT_SOUND_VOLUME_STEP);
} else {
play_1d_with_volume_step("sounds/enemies/zombie_hit.ogg", x, hit_pos, false, ZOMBIE_SOUND_VOLUME_STEP);
play_creature_hit_sound("sounds/enemies/zombie_hit.ogg", x, hit_pos, ZOMBIE_SOUND_VOLUME_STEP);
}
return;
}
@@ -60,9 +60,9 @@ void perform_axe_attack(int current_x) {
p.play_stationary("sounds/weapons/axe_hit.ogg", false);
// Play hit sound based on enemy type
if (get_bandit_at(current_x) != null) {
play_1d_with_volume_step("sounds/enemies/zombie_hit.ogg", x, current_x, false, BANDIT_SOUND_VOLUME_STEP);
play_creature_hit_sound("sounds/enemies/zombie_hit.ogg", x, current_x, BANDIT_SOUND_VOLUME_STEP);
} else {
play_1d_with_volume_step("sounds/enemies/zombie_hit.ogg", x, current_x, false, ZOMBIE_SOUND_VOLUME_STEP);
play_creature_hit_sound("sounds/enemies/zombie_hit.ogg", x, current_x, ZOMBIE_SOUND_VOLUME_STEP);
}
return;
}
@@ -180,10 +180,10 @@ void release_sling_attack(int player_x) {
if (hit_bandit) {
damage_bandit_at(target_x, damage);
p.play_1d("sounds/weapons/sling_hit.ogg", player_x, target_x, false);
play_1d_with_volume_step("sounds/enemies/zombie_hit.ogg", player_x, target_x, false, BANDIT_SOUND_VOLUME_STEP);
play_creature_hit_sound("sounds/enemies/zombie_hit.ogg", player_x, target_x, BANDIT_SOUND_VOLUME_STEP);
} else {
damage_zombie_at(target_x, damage);
p.play_1d("sounds/weapons/sling_hit.ogg", player_x, target_x, false);
play_1d_with_volume_step("sounds/enemies/zombie_hit.ogg", player_x, target_x, false, ZOMBIE_SOUND_VOLUME_STEP);
play_creature_hit_sound("sounds/enemies/zombie_hit.ogg", player_x, target_x, ZOMBIE_SOUND_VOLUME_STEP);
}
}

View File

@@ -107,6 +107,8 @@ const float FIREPIT_SOUND_VOLUME_STEP = 6.0; // 30 dB over 5 tiles
const int STREAM_SOUND_RANGE = 7;
const float STREAM_SOUND_VOLUME_STEP = 4.3; // 30 dB over 7 tiles
const float TREE_SOUND_VOLUME_STEP = 4.0; // Similar to snares for good audibility
// Mountain configuration
const int MOUNTAIN_SIZE = 60;
const int MOUNTAIN_MIN_ELEVATION = 0;

83
src/creature_audio.nvgt Normal file
View File

@@ -0,0 +1,83 @@
// Unified creature/enemy audio system
// Ensures consistent panning and distance behavior for all animated entities
//
// USAGE GUIDE:
// This system provides standardized audio functions for all creatures (zombies, bandits, animals).
// Using these functions ensures all creatures sound consistent to the player.
//
// When adding new creatures (sheep, cattle, horses, etc):
// 1. Define creature-specific constants in constants.nvgt:
// const float SHEEP_SOUND_VOLUME_STEP = 3.0;
// const int SHEEP_FOOTSTEP_MAX_DISTANCE = 5;
//
// 2. Use these functions in your creature update code:
// - play_creature_voice() for periodic sounds (bleats, moos, neighs) - returns handle, store it!
// - play_creature_footstep() when creature moves
// - play_creature_attack_sound() when creature attacks player/barricade
// - play_creature_death_sound() when creature dies
// - play_creature_hit_sound() when player damages creature
//
// 3. IMPORTANT: When creature dies, stop its sound before playing death sound:
// if (creature.sound_handle != -1) {
// p.destroy_sound(creature.sound_handle);
// creature.sound_handle = -1;
// }
// play_creature_death_sound("sounds/enemies/enemy_falls.ogg", x, pos, volume_step);
//
// 4. All sounds automatically use consistent panning/volume falloff
//
// Example for sheep:
// sheep.sound_handle = play_creature_voice("sounds/animals/sheep_bleat.ogg", x, sheep.position, SHEEP_SOUND_VOLUME_STEP);
// play_creature_footstep(x, sheep.position, BASE_END, GRASS_END, SHEEP_FOOTSTEP_MAX_DISTANCE, SHEEP_SOUND_VOLUME_STEP);
//
// Death handling example:
// if (sheep.sound_handle != -1) {
// p.destroy_sound(sheep.sound_handle);
// sheep.sound_handle = -1;
// }
// play_creature_death_sound("sounds/animals/sheep_death.ogg", x, sheep.position, SHEEP_SOUND_VOLUME_STEP);
// Default audio parameters for creatures
const float CREATURE_DEFAULT_VOLUME_STEP = 3.0;
const int CREATURE_DEFAULT_FOOTSTEP_DISTANCE = 6;
// Plays a creature's voice/alert sound with consistent positioning
// Returns the sound handle for tracking
int play_creature_voice(string sound_file, int listener_x, int creature_x, float volume_step = CREATURE_DEFAULT_VOLUME_STEP)
{
return play_1d_with_volume_step(sound_file, listener_x, creature_x, false, volume_step);
}
// Plays a creature's footstep sound with consistent positioning
// Only plays if within max_distance to avoid cluttering the soundscape
void play_creature_footstep(int listener_x, int creature_x, int base_end, int grass_end, int max_distance = CREATURE_DEFAULT_FOOTSTEP_DISTANCE, float volume_step = CREATURE_DEFAULT_VOLUME_STEP)
{
int distance = creature_x - listener_x;
if (distance < 0) {
distance = -distance;
}
if (distance > max_distance) {
return;
}
play_positional_footstep(listener_x, creature_x, base_end, grass_end, max_distance, volume_step);
}
// Plays a creature attack sound (hitting player, hitting barricade, etc.)
void play_creature_attack_sound(string sound_file, int listener_x, int creature_x, float volume_step = CREATURE_DEFAULT_VOLUME_STEP)
{
play_1d_with_volume_step(sound_file, listener_x, creature_x, false, volume_step);
}
// Plays a creature death/fall sound
void play_creature_death_sound(string sound_file, int listener_x, int creature_x, float volume_step = CREATURE_DEFAULT_VOLUME_STEP)
{
play_1d_with_volume_step(sound_file, listener_x, creature_x, false, volume_step);
}
// Plays a creature hit/damage sound (when player damages the creature)
void play_creature_hit_sound(string sound_file, int listener_x, int creature_x, float volume_step = CREATURE_DEFAULT_VOLUME_STEP)
{
play_1d_with_volume_step(sound_file, listener_x, creature_x, false, volume_step);
}

View File

@@ -45,9 +45,12 @@ class Tree {
int tree_distance = x - position;
if (tree_distance < 0) tree_distance = -tree_distance;
if (tree_distance <= 3) {
if (tree_distance <= 4) {
if (sound_handle == -1 || !p.sound_is_active(sound_handle)) {
sound_handle = p.play_1d("sounds/environment/tree.ogg", x, position, true);
if (sound_handle != -1) {
p.update_sound_positioning_values(sound_handle, -1.0, TREE_SOUND_VOLUME_STEP, true);
}
}
} else if (sound_handle != -1) {
p.destroy_sound(sound_handle);

View File

@@ -39,6 +39,7 @@ class Bandit {
int health;
string alert_sound;
string weapon_type; // "spear" or "axe"
int sound_handle;
timer move_timer;
timer alert_timer;
timer attack_timer;
@@ -55,6 +56,7 @@ class Bandit {
// Spawn somewhere in the expanded area
position = random(expansion_start, expansion_end);
health = BANDIT_HEALTH;
sound_handle = -1;
// Choose random alert sound
int sound_index = random(0, bandit_sounds.length() - 1);
@@ -616,7 +618,7 @@ void spawn_zombie() {
Zombie@ z = Zombie(spawn_x);
zombies.insert_last(z);
z.sound_handle = play_1d_with_volume_step(z.voice_sound, x, spawn_x, false, ZOMBIE_SOUND_VOLUME_STEP);
z.sound_handle = play_creature_voice(z.voice_sound, x, spawn_x, ZOMBIE_SOUND_VOLUME_STEP);
}
void try_attack_barricade(Zombie@ zombie) {
@@ -628,7 +630,7 @@ void try_attack_barricade(Zombie@ zombie) {
barricade_health -= damage;
if (barricade_health < 0) barricade_health = 0;
play_1d_with_volume_step("sounds/enemies/zombie_hits_player.ogg", x, zombie.position, false, ZOMBIE_SOUND_VOLUME_STEP);
play_creature_attack_sound("sounds/enemies/zombie_hits_player.ogg", x, zombie.position, ZOMBIE_SOUND_VOLUME_STEP);
// Resident defense counter-attack
if (can_residents_defend()) {
@@ -677,7 +679,7 @@ bool try_attack_player(Zombie@ zombie) {
player_health = 0;
}
play_1d_with_volume_step("sounds/enemies/zombie_hits_player.ogg", x, zombie.position, false, ZOMBIE_SOUND_VOLUME_STEP);
play_creature_attack_sound("sounds/enemies/zombie_hits_player.ogg", x, zombie.position, ZOMBIE_SOUND_VOLUME_STEP);
return true;
}
@@ -685,7 +687,7 @@ void update_zombie(Zombie@ zombie) {
if (zombie.groan_timer.elapsed > zombie.next_groan_delay) {
zombie.groan_timer.restart();
zombie.next_groan_delay = random(ZOMBIE_GROAN_MIN_DELAY, ZOMBIE_GROAN_MAX_DELAY);
zombie.sound_handle = play_1d_with_volume_step(zombie.voice_sound, x, zombie.position, false, ZOMBIE_SOUND_VOLUME_STEP);
zombie.sound_handle = play_creature_voice(zombie.voice_sound, x, zombie.position, ZOMBIE_SOUND_VOLUME_STEP);
}
if (try_attack_player(zombie)) {
@@ -723,7 +725,7 @@ void update_zombie(Zombie@ zombie) {
}
zombie.position = target_x;
play_positional_footstep(x, zombie.position, BASE_END, GRASS_END, ZOMBIE_FOOTSTEP_MAX_DISTANCE, ZOMBIE_SOUND_VOLUME_STEP);
play_creature_footstep(x, zombie.position, BASE_END, GRASS_END, ZOMBIE_FOOTSTEP_MAX_DISTANCE, ZOMBIE_SOUND_VOLUME_STEP);
}
void update_zombies() {
@@ -750,7 +752,7 @@ bool damage_zombie_at(int pos, int damage) {
p.destroy_sound(zombies[i].sound_handle);
zombies[i].sound_handle = -1;
}
play_1d_with_volume_step("sounds/enemies/enemy_falls.ogg", x, pos, false, ZOMBIE_SOUND_VOLUME_STEP);
play_creature_death_sound("sounds/enemies/enemy_falls.ogg", x, pos, ZOMBIE_SOUND_VOLUME_STEP);
zombies.remove_at(i);
}
return true;
@@ -809,7 +811,7 @@ void spawn_bandit(int expansion_start, int expansion_end) {
Bandit@ b = Bandit(spawn_x, expansion_start, expansion_end);
bandits.insert_last(b);
play_1d_with_volume_step(b.alert_sound, x, spawn_x, false, BANDIT_SOUND_VOLUME_STEP);
b.sound_handle = play_creature_voice(b.alert_sound, x, spawn_x, BANDIT_SOUND_VOLUME_STEP);
}
bool can_bandit_attack_player(Bandit@ bandit) {
@@ -903,7 +905,7 @@ void update_bandit(Bandit@ bandit) {
if (bandit.alert_timer.elapsed > bandit.next_alert_delay) {
bandit.alert_timer.restart();
bandit.next_alert_delay = random(BANDIT_ALERT_MIN_DELAY, BANDIT_ALERT_MAX_DELAY);
play_1d_with_volume_step(bandit.alert_sound, x, bandit.position, false, BANDIT_SOUND_VOLUME_STEP);
bandit.sound_handle = play_creature_voice(bandit.alert_sound, x, bandit.position, BANDIT_SOUND_VOLUME_STEP);
}
if (try_attack_player_bandit(bandit)) {
@@ -947,7 +949,7 @@ void update_bandit(Bandit@ bandit) {
bandit.wander_direction = -bandit.wander_direction;
} else {
bandit.position = target_x;
play_positional_footstep(x, bandit.position, BASE_END, GRASS_END, BANDIT_FOOTSTEP_MAX_DISTANCE, BANDIT_SOUND_VOLUME_STEP);
play_creature_footstep(x, bandit.position, BASE_END, GRASS_END, BANDIT_FOOTSTEP_MAX_DISTANCE, BANDIT_SOUND_VOLUME_STEP);
}
} else {
// Hit map boundary, reverse direction
@@ -990,7 +992,7 @@ void update_bandit(Bandit@ bandit) {
}
bandit.position = target_x;
play_positional_footstep(x, bandit.position, BASE_END, GRASS_END, BANDIT_FOOTSTEP_MAX_DISTANCE, BANDIT_SOUND_VOLUME_STEP);
play_creature_footstep(x, bandit.position, BASE_END, GRASS_END, BANDIT_FOOTSTEP_MAX_DISTANCE, BANDIT_SOUND_VOLUME_STEP);
}
}
@@ -1005,7 +1007,11 @@ bool damage_bandit_at(int pos, int damage) {
if (bandits[i].position == pos) {
bandits[i].health -= damage;
if (bandits[i].health <= 0) {
play_1d_with_volume_step("sounds/enemies/enemy_falls.ogg", x, pos, false, BANDIT_SOUND_VOLUME_STEP);
if (bandits[i].sound_handle != -1) {
p.destroy_sound(bandits[i].sound_handle);
bandits[i].sound_handle = -1;
}
play_creature_death_sound("sounds/enemies/enemy_falls.ogg", x, pos, BANDIT_SOUND_VOLUME_STEP);
bandits.remove_at(i);
} else {
}