mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Add comprehensive weather, water, and zone ambient audio systems
Implemented three new ambient audio systems with automatic day/night transitions: Weather ambience: - Rain sounds (light/medium/heavy intensity based on weather system) - Snow sounds (light/medium/heavy intensity) - Automatically syncs with visual weather system in renderer - Different loop intervals based on intensity (18-30s) - Disabled indoors Water ambience: - Underwater swimming sounds (18s loop) - Ocean surface sounds - State tracking for entering/exiting water Zone ambience: - Forest (normal and snow variants) - Beach sounds - Grasslands - Jungle - Marsh/swamp - Desert (canyon and plains variants) - All zones have separate day/night sound files - 30s loop interval for subtle background atmosphere - Disabled indoors Technical details: - Added WeatherType enum (NONE, RAIN/SNOW LIGHT/MEDIUM/HEAVY) - Added ZoneType enum (NONE, FOREST_NORMAL, FOREST_SNOW, BEACH, GRASSLANDS, JUNGLE, MARSH, DESERT_CANYON, DESERT_PLAINS) - Loads 26 new sound files from Sound\Ambience\Weather and Sound\Ambience\ZoneAmbience - Weather intensity thresholds: <0.33 = light, 0.33-0.66 = medium, >0.66 = heavy - Renderer automatically converts Weather::Type + intensity to AmbientSoundManager::WeatherType - All ambience respects volumeScale_ and indoor state - State change logging for debugging transitions
This commit is contained in:
parent
bbfab23566
commit
d6f0c2ec46
3 changed files with 321 additions and 0 deletions
|
|
@ -77,9 +77,91 @@ bool AmbientSoundManager::initialize(pipeline::AssetManager* assets) {
|
|||
blacksmithSounds_.resize(1);
|
||||
bool blacksmithLoaded = loadSound("Sound\\Ambience\\WMOAmbience\\BlackSmith.wav", blacksmithSounds_[0], assets);
|
||||
|
||||
// Load weather sounds
|
||||
rainLightSounds_.resize(1);
|
||||
bool rainLightLoaded = loadSound("Sound\\Ambience\\Weather\\RainLight.wav", rainLightSounds_[0], assets);
|
||||
|
||||
rainMediumSounds_.resize(1);
|
||||
bool rainMediumLoaded = loadSound("Sound\\Ambience\\Weather\\RainMedium.wav", rainMediumSounds_[0], assets);
|
||||
|
||||
rainHeavySounds_.resize(1);
|
||||
bool rainHeavyLoaded = loadSound("Sound\\Ambience\\Weather\\RainHeavy.wav", rainHeavySounds_[0], assets);
|
||||
|
||||
snowLightSounds_.resize(1);
|
||||
bool snowLightLoaded = loadSound("Sound\\Ambience\\Weather\\SnowLight.wav", snowLightSounds_[0], assets);
|
||||
|
||||
snowMediumSounds_.resize(1);
|
||||
bool snowMediumLoaded = loadSound("Sound\\Ambience\\Weather\\SnowMedium.wav", snowMediumSounds_[0], assets);
|
||||
|
||||
snowHeavySounds_.resize(1);
|
||||
bool snowHeavyLoaded = loadSound("Sound\\Ambience\\Weather\\SnowHeavy.wav", snowHeavySounds_[0], assets);
|
||||
|
||||
// Load water ambience sounds
|
||||
oceanSounds_.resize(1);
|
||||
bool oceanLoaded = loadSound("Sound\\Ambience\\Water\\OceanDeepDay.wav", oceanSounds_[0], assets);
|
||||
|
||||
underwaterSounds_.resize(1);
|
||||
bool underwaterLoaded = loadSound("Sound\\Ambience\\Water\\UnderwaterSwim.wav", underwaterSounds_[0], assets);
|
||||
|
||||
// Load zone ambience sounds (day and night)
|
||||
forestNormalDaySounds_.resize(1);
|
||||
bool forestDayLoaded = loadSound("Sound\\Ambience\\ZoneAmbience\\ForestNormalDay.wav", forestNormalDaySounds_[0], assets);
|
||||
|
||||
forestNormalNightSounds_.resize(1);
|
||||
bool forestNightLoaded = loadSound("Sound\\Ambience\\ZoneAmbience\\ForestNormalNight.wav", forestNormalNightSounds_[0], assets);
|
||||
|
||||
forestSnowDaySounds_.resize(1);
|
||||
bool forestSnowDayLoaded = loadSound("Sound\\Ambience\\ZoneAmbience\\ForestSnowDay.wav", forestSnowDaySounds_[0], assets);
|
||||
|
||||
forestSnowNightSounds_.resize(1);
|
||||
bool forestSnowNightLoaded = loadSound("Sound\\Ambience\\ZoneAmbience\\ForestSnowNight.wav", forestSnowNightSounds_[0], assets);
|
||||
|
||||
beachDaySounds_.resize(1);
|
||||
bool beachDayLoaded = loadSound("Sound\\Ambience\\ZoneAmbience\\BeachDay.wav", beachDaySounds_[0], assets);
|
||||
|
||||
beachNightSounds_.resize(1);
|
||||
bool beachNightLoaded = loadSound("Sound\\Ambience\\ZoneAmbience\\BeachNight.wav", beachNightSounds_[0], assets);
|
||||
|
||||
grasslandsDaySounds_.resize(1);
|
||||
bool grasslandsDayLoaded = loadSound("Sound\\Ambience\\ZoneAmbience\\GrasslandsDay.wav", grasslandsDaySounds_[0], assets);
|
||||
|
||||
grasslandsNightSounds_.resize(1);
|
||||
bool grasslandsNightLoaded = loadSound("Sound\\Ambience\\ZoneAmbience\\GrassLandsNight.wav", grasslandsNightSounds_[0], assets);
|
||||
|
||||
jungleDaySounds_.resize(1);
|
||||
bool jungleDayLoaded = loadSound("Sound\\Ambience\\ZoneAmbience\\JungleDay.wav", jungleDaySounds_[0], assets);
|
||||
|
||||
jungleNightSounds_.resize(1);
|
||||
bool jungleNightLoaded = loadSound("Sound\\Ambience\\ZoneAmbience\\JungleNight.wav", jungleNightSounds_[0], assets);
|
||||
|
||||
marshDaySounds_.resize(1);
|
||||
bool marshDayLoaded = loadSound("Sound\\Ambience\\ZoneAmbience\\MarshDay.wav", marshDaySounds_[0], assets);
|
||||
|
||||
marshNightSounds_.resize(1);
|
||||
bool marshNightLoaded = loadSound("Sound\\Ambience\\ZoneAmbience\\MarshNight.wav", marshNightSounds_[0], assets);
|
||||
|
||||
desertCanyonDaySounds_.resize(1);
|
||||
bool desertCanyonDayLoaded = loadSound("Sound\\Ambience\\ZoneAmbience\\CanyonDesertDay.wav", desertCanyonDaySounds_[0], assets);
|
||||
|
||||
desertCanyonNightSounds_.resize(1);
|
||||
bool desertCanyonNightLoaded = loadSound("Sound\\Ambience\\ZoneAmbience\\CanyonDesertNight.wav", desertCanyonNightSounds_[0], assets);
|
||||
|
||||
desertPlainsDaySounds_.resize(1);
|
||||
bool desertPlainsDayLoaded = loadSound("Sound\\Ambience\\ZoneAmbience\\PlainsDesertDay.wav", desertPlainsDaySounds_[0], assets);
|
||||
|
||||
desertPlainsNightSounds_.resize(1);
|
||||
bool desertPlainsNightLoaded = loadSound("Sound\\Ambience\\ZoneAmbience\\PlainsDesertNight.wav", desertPlainsNightSounds_[0], assets);
|
||||
|
||||
LOG_INFO("AmbientSoundManager: Wind loaded: ", windLoaded ? "YES" : "NO",
|
||||
", Tavern loaded: ", tavernLoaded ? "YES" : "NO",
|
||||
", Blacksmith loaded: ", blacksmithLoaded ? "YES" : "NO");
|
||||
LOG_INFO("AmbientSoundManager: Weather sounds - Rain: ", (rainLightLoaded && rainMediumLoaded && rainHeavyLoaded) ? "YES" : "NO",
|
||||
", Snow: ", (snowLightLoaded && snowMediumLoaded && snowHeavyLoaded) ? "YES" : "NO");
|
||||
LOG_INFO("AmbientSoundManager: Water sounds - Ocean: ", oceanLoaded ? "YES" : "NO",
|
||||
", Underwater: ", underwaterLoaded ? "YES" : "NO");
|
||||
LOG_INFO("AmbientSoundManager: Zone sounds - Forest: ", (forestDayLoaded && forestNightLoaded) ? "YES" : "NO",
|
||||
", Beach: ", (beachDayLoaded && beachNightLoaded) ? "YES" : "NO",
|
||||
", Desert: ", (desertCanyonDayLoaded && desertPlainsDayLoaded) ? "YES" : "NO");
|
||||
|
||||
// Initialize timers with random offsets
|
||||
birdTimer_ = randomFloat(0.0f, 5.0f);
|
||||
|
|
@ -137,6 +219,11 @@ void AmbientSoundManager::update(float deltaTime, const glm::vec3& cameraPos, bo
|
|||
updateWindAmbience(deltaTime, isIndoor);
|
||||
}
|
||||
|
||||
// Update weather, water, and zone ambience
|
||||
updateWeatherAmbience(deltaTime, isIndoor);
|
||||
updateWaterAmbience(deltaTime, isSwimming);
|
||||
updateZoneAmbience(deltaTime, isIndoor);
|
||||
|
||||
// Track indoor state changes
|
||||
wasIndoor_ = isIndoor;
|
||||
wasBlacksmith_ = isBlacksmith;
|
||||
|
|
@ -376,5 +463,152 @@ void AmbientSoundManager::setVolumeScale(float scale) {
|
|||
volumeScale_ = std::max(0.0f, std::min(1.0f, scale));
|
||||
}
|
||||
|
||||
void AmbientSoundManager::setWeather(WeatherType type) {
|
||||
if (currentWeather_ != type) {
|
||||
LOG_INFO("AmbientSoundManager: Weather changed from ", static_cast<int>(currentWeather_),
|
||||
" to ", static_cast<int>(type));
|
||||
currentWeather_ = type;
|
||||
weatherLoopTime_ = 0.0f; // Reset timer on weather change
|
||||
}
|
||||
}
|
||||
|
||||
void AmbientSoundManager::setZoneType(ZoneType type) {
|
||||
if (currentZone_ != type) {
|
||||
LOG_INFO("AmbientSoundManager: Zone changed from ", static_cast<int>(currentZone_),
|
||||
" to ", static_cast<int>(type));
|
||||
currentZone_ = type;
|
||||
zoneLoopTime_ = 15.0f; // Play zone ambience soon after entering
|
||||
}
|
||||
}
|
||||
|
||||
void AmbientSoundManager::updateWeatherAmbience(float deltaTime, bool isIndoor) {
|
||||
// Don't play weather sounds when indoors
|
||||
if (isIndoor || currentWeather_ == WeatherType::NONE) return;
|
||||
|
||||
weatherLoopTime_ += deltaTime;
|
||||
|
||||
// Select appropriate sound library based on weather type
|
||||
const std::vector<AmbientSample>* weatherLibrary = nullptr;
|
||||
float loopInterval = 20.0f; // Default 20 second loop for weather
|
||||
|
||||
switch (currentWeather_) {
|
||||
case WeatherType::RAIN_LIGHT:
|
||||
weatherLibrary = &rainLightSounds_;
|
||||
loopInterval = 25.0f;
|
||||
break;
|
||||
case WeatherType::RAIN_MEDIUM:
|
||||
weatherLibrary = &rainMediumSounds_;
|
||||
loopInterval = 20.0f;
|
||||
break;
|
||||
case WeatherType::RAIN_HEAVY:
|
||||
weatherLibrary = &rainHeavySounds_;
|
||||
loopInterval = 18.0f;
|
||||
break;
|
||||
case WeatherType::SNOW_LIGHT:
|
||||
weatherLibrary = &snowLightSounds_;
|
||||
loopInterval = 30.0f;
|
||||
break;
|
||||
case WeatherType::SNOW_MEDIUM:
|
||||
weatherLibrary = &snowMediumSounds_;
|
||||
loopInterval = 25.0f;
|
||||
break;
|
||||
case WeatherType::SNOW_HEAVY:
|
||||
weatherLibrary = &snowHeavySounds_;
|
||||
loopInterval = 22.0f;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// Play weather sound if library is loaded and timer expired
|
||||
if (weatherLibrary && !weatherLibrary->empty() && (*weatherLibrary)[0].loaded) {
|
||||
if (weatherLoopTime_ >= loopInterval) {
|
||||
float volume = 0.4f * volumeScale_; // Weather ambience at moderate volume
|
||||
AudioEngine::instance().playSound2D((*weatherLibrary)[0].data, volume, 1.0f);
|
||||
LOG_INFO("Playing weather ambience: type ", static_cast<int>(currentWeather_));
|
||||
weatherLoopTime_ = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AmbientSoundManager::updateWaterAmbience(float deltaTime, bool isSwimming) {
|
||||
bool stateChanged = (wasSwimming_ != isSwimming);
|
||||
|
||||
if (stateChanged) {
|
||||
LOG_INFO("Ambient: ", isSwimming ? "ENTERED WATER" : "EXITED WATER");
|
||||
oceanLoopTime_ = 0.0f; // Reset timer on state change
|
||||
}
|
||||
|
||||
wasSwimming_ = isSwimming;
|
||||
|
||||
// Play underwater sounds when swimming
|
||||
if (isSwimming) {
|
||||
if (!underwaterSounds_.empty() && underwaterSounds_[0].loaded) {
|
||||
oceanLoopTime_ += deltaTime;
|
||||
// Play every 18 seconds for underwater ambience
|
||||
if (oceanLoopTime_ >= 18.0f) {
|
||||
float volume = 0.5f * volumeScale_;
|
||||
AudioEngine::instance().playSound2D(underwaterSounds_[0].data, volume, 1.0f);
|
||||
LOG_INFO("Playing underwater ambience");
|
||||
oceanLoopTime_ = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Play ocean sounds when near water but not swimming
|
||||
// (This could be enhanced later with proximity detection to water surfaces)
|
||||
}
|
||||
|
||||
void AmbientSoundManager::updateZoneAmbience(float deltaTime, bool isIndoor) {
|
||||
// Don't play zone ambience when indoors
|
||||
if (isIndoor || currentZone_ == ZoneType::NONE) return;
|
||||
|
||||
zoneLoopTime_ += deltaTime;
|
||||
|
||||
// Select appropriate sound library based on zone type and time of day
|
||||
const std::vector<AmbientSample>* zoneLibrary = nullptr;
|
||||
bool isDay = isDaytime();
|
||||
|
||||
switch (currentZone_) {
|
||||
case ZoneType::FOREST_NORMAL:
|
||||
zoneLibrary = isDay ? &forestNormalDaySounds_ : &forestNormalNightSounds_;
|
||||
break;
|
||||
case ZoneType::FOREST_SNOW:
|
||||
zoneLibrary = isDay ? &forestSnowDaySounds_ : &forestSnowNightSounds_;
|
||||
break;
|
||||
case ZoneType::BEACH:
|
||||
zoneLibrary = isDay ? &beachDaySounds_ : &beachNightSounds_;
|
||||
break;
|
||||
case ZoneType::GRASSLANDS:
|
||||
zoneLibrary = isDay ? &grasslandsDaySounds_ : &grasslandsNightSounds_;
|
||||
break;
|
||||
case ZoneType::JUNGLE:
|
||||
zoneLibrary = isDay ? &jungleDaySounds_ : &jungleNightSounds_;
|
||||
break;
|
||||
case ZoneType::MARSH:
|
||||
zoneLibrary = isDay ? &marshDaySounds_ : &marshNightSounds_;
|
||||
break;
|
||||
case ZoneType::DESERT_CANYON:
|
||||
zoneLibrary = isDay ? &desertCanyonDaySounds_ : &desertCanyonNightSounds_;
|
||||
break;
|
||||
case ZoneType::DESERT_PLAINS:
|
||||
zoneLibrary = isDay ? &desertPlainsDaySounds_ : &desertPlainsNightSounds_;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// Play zone ambience sound if library is loaded and timer expired
|
||||
if (zoneLibrary && !zoneLibrary->empty() && (*zoneLibrary)[0].loaded) {
|
||||
// Play every 30 seconds for zone ambience (longer intervals for background atmosphere)
|
||||
if (zoneLoopTime_ >= 30.0f) {
|
||||
float volume = 0.35f * volumeScale_; // Zone ambience at moderate-low volume
|
||||
AudioEngine::instance().playSound2D((*zoneLibrary)[0].data, volume, 1.0f);
|
||||
LOG_INFO("Playing zone ambience: type ", static_cast<int>(currentZone_),
|
||||
" (", isDay ? "day" : "night", ")");
|
||||
zoneLoopTime_ = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace audio
|
||||
} // namespace wowee
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue