diff --git a/Adventures in Lestoria/AdventuresInLestoria.cpp b/Adventures in Lestoria/AdventuresInLestoria.cpp index 0461e3bc..90986ca9 100644 --- a/Adventures in Lestoria/AdventuresInLestoria.cpp +++ b/Adventures in Lestoria/AdventuresInLestoria.cpp @@ -137,8 +137,9 @@ AiL::AiL() std::string ITEM_STATS_CONFIG = CONFIG_PATH + "item_stats_config"_S; utils::datafile::Read(DATA,ITEM_STATS_CONFIG); - for(auto&[key,value]:DATA.GetProperty("ItemConfiguration").GetKeys()){ - std::string config = DATA["ItemConfiguration"][key].GetString(); + auto keys=DATA.GetProperty("ItemConfiguration"); + for(auto&[key,value]:keys){ + std::string config=DATA["ItemConfiguration"][key].GetString(); utils::datafile::Read(DATA,CONFIG_PATH + "item_directory"_S + config); } @@ -150,6 +151,12 @@ AiL::AiL() utils::datafile::Read(DATA,CONFIG_PATH + "class_directory"_S + cl + ".txt"); } + std::string BGM_CONFIG = CONFIG_PATH + "bgm_config"_S; + utils::datafile::Read(DATA,BGM_CONFIG); + + std::string BGM_EVENTS_CONFIG = CONFIG_PATH + "event_config"_S; + utils::datafile::Read(DATA,BGM_EVENTS_CONFIG); + utils::datafile::DEBUG_ACCESS_OPTIONS="debug_access_options"_I; sAppName = "GAME_NAME"_S; @@ -236,6 +243,8 @@ bool AiL::OnUserCreate(){ Stats::InitializeDamageReductionTable(); + Audio::Initialize(); + utils::datafile::INITIAL_SETUP_COMPLETE=true; ValidateGameStatus(); //Checks to make sure everything has been initialized properly. diff --git a/Adventures in Lestoria/Audio.cpp b/Adventures in Lestoria/Audio.cpp index 473f1266..72a49bf6 100644 --- a/Adventures in Lestoria/Audio.cpp +++ b/Adventures in Lestoria/Audio.cpp @@ -40,21 +40,192 @@ All rights reserved. #include "DEFINES.h" INCLUDE_game +INCLUDE_DATA + +float Audio::defaultFadeTime; + +void Audio::Initialize(){ + Self().events.insert("Default Volume"); + for(auto&[key,data]:DATA["Events"]){ + Self().events.insert(key); + } + for(auto&[songFileName,size]:DATA["BGM"]){ + auto&data=DATA["BGM"][songFileName]; + if(songFileName!="Default Fade Time"){ + int channelCounter=0; + + BGM&bgm=Self().bgm[songFileName]; + + bgm.SetFileName(songFileName); + bgm.SetName(data["Track Name"].GetString()); + + while(data.HasProperty(std::format("channel[{}]",channelCounter))){ + std::string channelName=data[std::format("channel[{}]",channelCounter)].GetString(); + if(!std::filesystem::exists("bgm_directory"_S+channelName))ERR(std::format("WARNING! Could not load file {} for track {}",channelName,songFileName)); + bgm.AddChannel(channelName); + channelCounter++; + } + + if(!data.HasProperty("Default Volume"))ERR(std::format("WARNING! Track {} does not have a Default Volume parameter!",bgm.GetName())); + if(data["Default Volume"].GetValueCount()!=bgm.GetChannelCount())ERR(std::format("WARNING! Default Volume parameters do not match channel count. {} != {}",data["Default Volume"].GetValueCount(),bgm.GetChannelCount())); + + VolumeList volumes; + for(int i=0;iaudioEngine.audioEngine; } void Audio::Play(const std::string_view sound){ - Engine().Play(std::string(sound)); + Engine().Play(std::string(sound)); }; -void Audio::PlayBGM(const std::string_view sound,const bool loop=true){ - if(Engine().LoadS) - Engine().Play(std::string(sound)); +void Audio::PlayBGM(const std::string_view sound,const bool loop){ + BGM&track=Self().bgm[std::string(sound)]; + StopBGM(); //Stop any currently playing track. + track.Load(); + for(int channelListIndex=0;int trackID:track.GetChannelIDs()){ + Engine().SetVolume(trackID,track.GetVolume(Self().currentAudioEvent,channelListIndex)); + Engine().Play(trackID,loop); + channelListIndex++; + } }; +void Audio::StopBGM(){ + if(Self().BGMIsPlaying()){ + BGM¤tTrack=Self().bgm[Self().currentBGM]; + for(int trackID:currentTrack.GetChannelIDs()){ + Engine().Stop(trackID); + } + } +} + +const bool Audio::BGMIsPlaying(){ + return Self().currentBGM.length()>0; +} + +const Volume&Audio::BGM::GetVolume(const Event&eventName,const ChannelID&id)const{ + return eventVolumes.GetVolumes(eventName).at(id); +} + +void Audio::BGM::Load(){ + BGM&bgm=Self().bgm[Self().currentBGM]; + if(Self().BGMIsPlaying()){ + bgm.Unload(); + } + Self().currentBGM=songFileName; + BGM&newBgm=Self().bgm[songFileName]; + if(newBgm.channels.size()>0)ERR(std::format("WARNING! The size of the channels list is greater than zero! Size: {}",bgm.channels.size())); + for(const ChannelName&channel:newBgm.GetChannels()){ + ChannelID soundID=Engine().LoadSound("bgm_directory"_S+channel); + newBgm.channels.push_back(soundID); + } +} + +void Audio::BGM::Unload(){ + BGM&bgm=Self().bgm[Self().currentBGM]; + for(const ChannelID&id:channels){ + Engine().UnloadSound(id); + } + channels.clear(); + Self().currentBGM=""; +} + +const ChannelID&Audio::BGM::GetChannelID(const int index){ + return channels[index]; +} + +const ChannelIDList&Audio::BGM::GetChannelIDs()const{ + return channels; +} + +const std::vector&Audio::BGM::GetChannels()const{ + return channelNames; +} + +void Audio::BGM::SetFadeTime(const float fadeTime){ + this->fadeTime=fadeTime; +} + +void Audio::BGM::AddEventVolumes(const Event&eventName,const VolumeList&volumes){ + eventVolumes.AddEventInfo(eventName,volumes); +} + +const size_t Audio::BGM::GetChannelCount()const{ + return channelNames.size(); +} + +const SongName&Audio::BGM::GetName()const{ + return songName; +} + +void Audio::BGM::SetName(std::string_view name){ + songName=name; +} + +void Audio::BGM::SetFileName(std::string_view name){ + songFileName=name; +} + +void Audio::BGM::AddChannel(const ChannelName&name){ + channelNames.push_back(name); +} + +const VolumeList&Audio::EventData::GetVolumes(const Event&event)const{ + if(eventInfo.find(event)!=eventInfo.end())return eventInfo.at(event); + return eventInfo.at("Default Volume"); +} + +void Audio::EventData::AddEventInfo(const Event&eventName,const VolumeList&volumes){ + eventInfo[eventName]=volumes; +} + +Audio&Audio::Self(){ + return game->audioEngine; +} + +const Event&Audio::GetAudioEvent(){ + return Self().currentAudioEvent; +} +void Audio::SetAudioEvent(const Event&eventName){ + if(Self().events.find(eventName)==Self().events.end())ERR(std::format("WARNING! cannot find event {}",eventName)); + + Self().currentAudioEvent=eventName; + + if(Audio::BGMIsPlaying()){ + BGM¤tBgm=Self().bgm[Self().currentBGM]; + for(int currentTrackIndex=0;int trackID:currentBgm.GetChannelIDs()){ + Engine().SetVolume(trackID,currentBgm.GetVolume(eventName,currentTrackIndex)); + currentTrackIndex++; + } + } +} + std::string operator""_SFX(const char*key,size_t length){ return "sfx_directory"_S+std::string(key,length); -} -std::string operator""_BGM(const char*key,size_t length){ - return "bgm_directory"_S+std::string(key,length); } \ No newline at end of file diff --git a/Adventures in Lestoria/Audio.h b/Adventures in Lestoria/Audio.h index cde143d5..bf23b54d 100644 --- a/Adventures in Lestoria/Audio.h +++ b/Adventures in Lestoria/Audio.h @@ -38,20 +38,66 @@ All rights reserved. #pragma once #include "olcPGEX_MiniAudio.h" #include "config.h" +#include + +using SongName=std::string; +using Event=std::string; +using ChannelName=std::string; +using ChannelID=int; +using ChannelIDList=std::vector; +using Volume=float; +using VolumeList=std::vector; class Audio{ - class BGM{ - std::vectorchannels; - public: - Load(); - Unload(); - }; - MiniAudio audioEngine; public: + static Audio&Self(); static MiniAudio&Engine(); + static void Initialize(); static void Play(const std::string_view sound); + //Play a BGM given a name found in bgm.txt configuration file. static void PlayBGM(const std::string_view sound,const bool loop=true); + static void StopBGM(); + static const Event&GetAudioEvent(); + static void SetAudioEvent(const Event&eventName); + static const bool BGMIsPlaying(); +private: + class EventData{ + public: + void AddEventInfo(const Event&eventName,const VolumeList&volumes); + const VolumeList&GetVolumes(const Event&event)const; + private: + std::mapeventInfo; + }; + class BGM{ + public: + void Load(); + const size_t GetChannelCount()const; + const std::vector&GetChannels()const; + const SongName&GetName()const; + const Volume&GetVolume(const Event&eventName,const ChannelID&id)const; + void SetName(std::string_view name); + void SetFileName(std::string_view name); + void AddChannel(const ChannelName&name); + void AddEventVolumes(const Event&eventName,const VolumeList&volumes); + void SetFadeTime(const float fadeTime); + const ChannelID&GetChannelID(const int index); + const ChannelIDList&GetChannelIDs()const; + private: + std::string songName; //Name of the track. + std::string songFileName; //Name of the key in bgm. + ChannelIDList channels; + std::vectorchannelNames; + EventData eventVolumes; + float fadeTime="BGM.Default Fade Time"_F; + void Unload(); + }; +private: + MiniAudio audioEngine; + SongName currentBGM=""; + std::mapbgm; + std::setevents; + static float defaultFadeTime; + Event currentAudioEvent="Default Volume"; }; -std::string operator""_SFX(const char*key,size_t length); -std::string operator""_BGM(const char*key,size_t length); \ No newline at end of file +std::string operator""_SFX(const char*key,size_t length); \ No newline at end of file diff --git a/Adventures in Lestoria/State_OverworldMap.cpp b/Adventures in Lestoria/State_OverworldMap.cpp index bbc062c4..6b3a1bb1 100644 --- a/Adventures in Lestoria/State_OverworldMap.cpp +++ b/Adventures in Lestoria/State_OverworldMap.cpp @@ -109,6 +109,24 @@ void State_OverworldMap::OnUserUpdate(AiL*game){ if(game->GetKey(K1).bPressed){ Audio::Play("sfx100v2_loop_water_01.mp3"_SFX); } + if(game->GetKey(F1).bPressed){ + Audio::PlayBGM("foresty1_1"); + }else + if(game->GetKey(F2).bPressed){ + Audio::PlayBGM("foresty0"); + } + if(game->GetKey(K2).bPressed){ + Audio::SetAudioEvent("Default Volume"); + } + if(game->GetKey(K3).bPressed){ + Audio::SetAudioEvent("LowHealth"); + } + if(game->GetKey(K4).bPressed){ + Audio::SetAudioEvent("InCombat"); + } + if(game->GetKey(K5).bPressed){ + Audio::SetAudioEvent("Underwater"); + } #pragma region Handle Connection Point Clicking and Movement for(ConnectionPoint&cp:connections){ diff --git a/Adventures in Lestoria/TODO.txt b/Adventures in Lestoria/TODO.txt index d493d8ae..1d7dd1e5 100644 --- a/Adventures in Lestoria/TODO.txt +++ b/Adventures in Lestoria/TODO.txt @@ -18,7 +18,7 @@ Settings Menu -Upon pressing a key, check if the key is bound to another option, if so, remove that bind from the list. Up to two keys may be binded per action. -We have to save keybinds to the save file. - +-Smooth Movement January 31st ============ @@ -41,4 +41,6 @@ Story proofreading/correcting/storyboarding - Loading Screen - Title Screen setpieces -- Export/Import Save Files Online/Offline \ No newline at end of file +- Export/Import Save Files Online/Offline + +- Consider controls for fine-tuning music and how they sound during events. \ No newline at end of file diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 23338e9d..9cba92e0 100644 --- a/Adventures in Lestoria/Version.h +++ b/Adventures in Lestoria/Version.h @@ -39,7 +39,7 @@ All rights reserved. #define VERSION_MAJOR 0 #define VERSION_MINOR 2 #define VERSION_PATCH 1 -#define VERSION_BUILD 5353 +#define VERSION_BUILD 5379 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/assets/config/bgm/bgm.txt b/Adventures in Lestoria/assets/config/bgm/bgm.txt index c460ae08..b25365f9 100644 --- a/Adventures in Lestoria/assets/config/bgm/bgm.txt +++ b/Adventures in Lestoria/assets/config/bgm/bgm.txt @@ -1,25 +1,51 @@ -#Song title followed by filenames for individual parts -foresty1_1 +BGM { - # High - channel[0]=foresty1_1_1.mp3 - # Low - channel[1]=foresty1_1_2.mp3 + Default Fade Time = 1.0 - # Underwater High - channel[2]=foresty1_1_alt1.mp3 - # Underwater Low - channel[3]=foresty1_1_alt2.mp3 + #Song title followed by filenames for individual parts + foresty1_1 + { + Track Name = Foresty + + # High + channel[0]=foresty1_1_1.mp3 + # Low + channel[1]=foresty1_1_2.mp3 - Default Volume = 70%,50%,0%,0% + # Underwater High + channel[2]=foresty1_1_alt1.mp3 + # Underwater Low + channel[3]=foresty1_1_alt2.mp3 - # Transition time between one phase to the next. - Fade Speed = 2.0 + Default Volume = 70%,50%,0%,0% - Events + # Transition time between one phase to the next. + Fade Time = 2.0 + + Events + { + LowHealth = 50%,60%,20%,20% + InCombat = 90%,100%,0%,0% + Underwater = 0%,0%,100%,100% + } + } + foresty0 { - LowHealth = 50%,60%,20%,20% - InCombat = 90%,100%,0%,0% - Underwater = 0%,0%,100%,100% + Track Name = Foresty Preview + + channel[0]=foresty0.mp3 + channel[1]=foresty0_alt.mp3 + + Default Volume = 70%,0% + + # Transition time between one phase to the next. + Fade Time = 2.0 + + Events + { + LowHealth = 50%,20% + InCombat = 100%,0% + Underwater = 0%,100% + } } } \ No newline at end of file diff --git a/Adventures in Lestoria/assets/config/configuration.txt b/Adventures in Lestoria/assets/config/configuration.txt index f4ba22c5..8da84c2f 100644 --- a/Adventures in Lestoria/assets/config/configuration.txt +++ b/Adventures in Lestoria/assets/config/configuration.txt @@ -66,10 +66,10 @@ sfx_directory = assets/sounds/ bgm_directory = assets/music/ # Path to bgm configuration -bgm_config = bgm.txt +bgm_config = bgm/bgm.txt # Path to bgm events configuration -event_config = events.txt +event_config = bgm/events.txt # Path to character images character_image_location = characters/ diff --git a/Adventures in Lestoria/assets/music/foresty0.mp3 b/Adventures in Lestoria/assets/music/foresty0.mp3 new file mode 100644 index 00000000..9cfe85ac Binary files /dev/null and b/Adventures in Lestoria/assets/music/foresty0.mp3 differ diff --git a/Adventures in Lestoria/assets/music/foresty0_alt.mp3 b/Adventures in Lestoria/assets/music/foresty0_alt.mp3 new file mode 100644 index 00000000..cb83fcc3 Binary files /dev/null and b/Adventures in Lestoria/assets/music/foresty0_alt.mp3 differ