Make loading for BGMs loopless.
This commit is contained in:
parent
42d4e794c7
commit
76c1487871
@ -1823,6 +1823,7 @@ void AiL::InitializeLevel(std::string mapFile,MapName map){
|
||||
|
||||
void AiL::LoadLevel(MapName map){
|
||||
LoadingScreen::loading=true;
|
||||
#pragma region Reset all data (Loading phase 1)
|
||||
if(game->MAP_DATA.count(map)==0)ERR(std::format("WARNING! Could not load map {}! Does not exist! Refer to levels.txt for valid maps.",map));
|
||||
if(game->MAP_DATA[map].GetMapType()=="Hub"&&GameState::STATE!=GameState::states[States::GAME_HUB])ERR("WARNING! A hub level should only be initiated in the GAME_HUB game state!");
|
||||
|
||||
@ -1857,9 +1858,11 @@ void AiL::LoadLevel(MapName map){
|
||||
GetPlayer()->GetCastInfo()={};
|
||||
GetPlayer()->ResetAccumulatedXP();
|
||||
|
||||
#pragma endregion
|
||||
|
||||
ZONE_LIST=game->MAP_DATA[game->GetCurrentLevel()].ZoneData;
|
||||
|
||||
#pragma region Monster Spawn Data Setup
|
||||
#pragma region Monster Spawn Data Setup (Loading phase 2)
|
||||
for(auto&[key,value]:MAP_DATA[map].SpawnerData){
|
||||
SpawnerTag&spawnData=MAP_DATA[map].SpawnerData[key];
|
||||
std::vector<std::pair<std::string,vf2d>>monster_list;
|
||||
@ -1873,7 +1876,7 @@ void AiL::LoadLevel(MapName map){
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Identify Upper Foreground Tiles
|
||||
#pragma region Identify Upper Foreground Tiles (Loading phase 3)
|
||||
auto GetUpperZones=[&](){
|
||||
for(auto&zoneSet:MAP_DATA[map].ZoneData){
|
||||
if(zoneSet.first=="UpperZone"){ //We are interested in all upper zones.
|
||||
@ -1902,7 +1905,7 @@ void AiL::LoadLevel(MapName map){
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Foreground and Upper Foreground Tile Fade Group Setup
|
||||
#pragma region Foreground and Upper Foreground Tile Fade Group Setup (Loading phase 4)
|
||||
std::set<vi2d>foregroundTilesAdded,upperForegroundTilesAdded;
|
||||
for(int x=0;x<GetCurrentMapData().width;x++){
|
||||
for(int y=0;y<GetCurrentMapData().height;y++){
|
||||
@ -1992,7 +1995,7 @@ void AiL::LoadLevel(MapName map){
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Foreground and Upper Foreground Tile Fade Group Individual Object Grouping Splitting
|
||||
#pragma region Foreground and Upper Foreground Tile Fade Group Individual Object Grouping Splitting (Loading phase 5)
|
||||
auto SplitUp=[&](std::vector<TileGroup>&group){
|
||||
std::multimap<vi2d,TileRenderData>data;
|
||||
using TileDataGroup=std::multimap<vi2d,TileRenderData>; //See below.
|
||||
@ -2059,7 +2062,7 @@ void AiL::LoadLevel(MapName map){
|
||||
SplitUp(upperForegroundTileGroups);
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Bridge Layer Setup
|
||||
#pragma region Bridge Layer Setup (Loading Phase 6)
|
||||
bridgeLayerIndex=-1;
|
||||
for(int counter=0;LayerTag&layer:MAP_DATA[map].LayerData){
|
||||
if(IsBridgeLayer(layer)){
|
||||
@ -2069,6 +2072,7 @@ void AiL::LoadLevel(MapName map){
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Setup NPCs (Loading Phase 7)
|
||||
for(NPCData data:game->MAP_DATA[game->GetCurrentLevel()].npcs){
|
||||
if(Unlock::IsUnlocked(data.unlockCondition)){
|
||||
MONSTER_LIST.push_back(Monster{data.spawnPos,MONSTER_DATA[data.name]});
|
||||
@ -2076,7 +2080,9 @@ void AiL::LoadLevel(MapName map){
|
||||
MONSTER_LIST.back().npcData=data;
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Setup Player and Camera (Loading Phase 8)
|
||||
player->GetAbility1().cooldown=0.f;
|
||||
player->GetAbility2().cooldown=0.f;
|
||||
player->GetAbility3().cooldown=0.f;
|
||||
@ -2091,8 +2097,12 @@ void AiL::LoadLevel(MapName map){
|
||||
|
||||
vf2d cameraStartPos=player->GetPos()+vf2d(-24*6,0);
|
||||
camera.MoveCamera(cameraStartPos);
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Setup Pathfinding (Loading Phase 9)
|
||||
pathfinder.Initialize();
|
||||
#pragma endregion
|
||||
|
||||
Audio::SetAudioEvent("Default Volume");
|
||||
game->audioEngine.fullyLoaded=true; //We assume there's no audio to load, so we just set the audio as fully loaded by default.
|
||||
if(MAP_DATA[map].bgmSongName.length()>0){
|
||||
|
@ -39,6 +39,7 @@ All rights reserved.
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include "DEFINES.h"
|
||||
#include "util.h"
|
||||
#include "LoadingScreen.h"
|
||||
|
||||
INCLUDE_game
|
||||
INCLUDE_DATA
|
||||
@ -121,12 +122,21 @@ const size_t Audio::LoadAndPlay(const std::string_view sound,const bool loop){
|
||||
Engine().Play(soundID,loop);
|
||||
return soundID;
|
||||
};
|
||||
void Audio::PlayBGM(const std::string_view sound,const bool loop){
|
||||
void Audio::PrepareBGM(const std::string_view sound,const bool loop){
|
||||
BGM&track=Self().bgm[std::string(sound)];
|
||||
Self().fullyLoaded=false;
|
||||
StopBGM(); //Stop any currently playing track.
|
||||
Self().playParams={std::string(sound),loop};
|
||||
Self().playBGMWaitTime=0.7f;
|
||||
|
||||
#pragma region Internal Loading Loop Setup
|
||||
Self().trackLoadStarted=false;
|
||||
Self().trackLoadComplete=false;
|
||||
Self().channelPlayingStarted=false;
|
||||
Self().channelPlayingComplete=false;
|
||||
int currentLoopIndex=0;
|
||||
#pragma endregion
|
||||
Self().immediatelyLoadAudio=false;
|
||||
};
|
||||
|
||||
void Audio::StopBGM(){
|
||||
@ -142,24 +152,35 @@ 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);
|
||||
const Volume&Audio::BGM::GetVolume(const Event&eventName,const int&index)const{
|
||||
return eventVolumes.GetVolumes(eventName).at(index);
|
||||
}
|
||||
|
||||
void Audio::BGM::Load(){
|
||||
if(Self().BGMIsPlaying()){
|
||||
if(Self().GetTrackName()==songFileName)return; //We are already playing the current track.
|
||||
BGM&bgm=Self().bgm[Self().GetTrackName()];
|
||||
if(!Self().trackLoadStarted){
|
||||
Self().trackLoadStarted=true;
|
||||
if(Self().BGMIsPlaying()){
|
||||
bgm.Unload();
|
||||
if(Self().GetTrackName()==songFileName)return; //We are already playing the current track.
|
||||
BGM&bgm=Self().bgm[Self().GetTrackName()];
|
||||
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: {}",newBgm.channels.size()));
|
||||
for(const ChannelName&channel:newBgm.GetChannels()){
|
||||
Self().currentBGM=songFileName;
|
||||
Self().currentLoopIndex=0;
|
||||
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: {}",newBgm.channels.size()));
|
||||
}else{
|
||||
BGM&newBgm=Self().bgm[songFileName];
|
||||
const ChannelName&channel=newBgm.GetChannels()[Self().currentLoopIndex];
|
||||
ChannelID soundID=Engine().LoadSound("bgm_directory"_S+channel);
|
||||
newBgm.channels.push_back(soundID);
|
||||
#pragma region Handle threaded loop indexing
|
||||
Self().currentLoopIndex++;
|
||||
if(Self().currentLoopIndex>=newBgm.GetChannels().size()){
|
||||
Self().trackLoadComplete=true;
|
||||
}
|
||||
#pragma endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,27 +276,54 @@ const SongName&Audio::GetTrackName(){
|
||||
return Self().currentBGM;
|
||||
}
|
||||
|
||||
void Audio::Update(){
|
||||
if(Self().playBGMWaitTime>0.f){
|
||||
Self().playBGMWaitTime=std::max(Self().playBGMWaitTime-game->GetElapsedTime(),0.f);
|
||||
if(Self().playBGMWaitTime==0.f){
|
||||
BGM&track=Self().bgm[Self().playParams.sound];
|
||||
void Audio::UpdateLoop(){
|
||||
if(Self().playBGMWaitTime==0.f){
|
||||
BGM&track=Self().bgm[Self().playParams.sound];
|
||||
if(!Self().trackLoadComplete){
|
||||
track.Load();
|
||||
Self().prevVolumes.clear();
|
||||
Self().targetVolumes.clear();
|
||||
Self().fadeToTargetVolumeTime=0.f;
|
||||
for(int channelListIndex=0;int trackID:track.GetChannelIDs()){
|
||||
float channelVol=track.GetVolume(Self().currentAudioEvent,channelListIndex);
|
||||
}else
|
||||
if(!Self().channelPlayingComplete){
|
||||
if(!Self().channelPlayingStarted){
|
||||
Self().prevVolumes.clear();
|
||||
Self().targetVolumes.clear();
|
||||
Self().fadeToTargetVolumeTime=0.f;
|
||||
Self().currentLoopIndex=0;
|
||||
Self().channelPlayingStarted=true;
|
||||
}else{
|
||||
|
||||
int trackID=track.GetChannelIDs()[Self().currentLoopIndex];
|
||||
float channelVol=track.GetVolume(Self().currentAudioEvent,Self().currentLoopIndex);
|
||||
Self().prevVolumes.push_back(channelVol);
|
||||
Self().targetVolumes.push_back(channelVol);
|
||||
Engine().SetVolume(trackID,channelVol*GetBGMVolume());
|
||||
Engine().Play(trackID,Self().playParams.loop);
|
||||
channelListIndex++;
|
||||
#pragma region Handle threaded loop indexing
|
||||
Self().currentLoopIndex++;
|
||||
if(Self().currentLoopIndex>=track.GetChannelIDs().size()){
|
||||
Self().channelPlayingComplete=true;
|
||||
}
|
||||
#pragma endregion
|
||||
}
|
||||
}else{
|
||||
Self().fullyLoaded=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Audio::PlayBGM(const std::string_view sound,const bool loop){
|
||||
PrepareBGM(sound,loop);
|
||||
Self().immediatelyLoadAudio=true;
|
||||
}
|
||||
|
||||
void Audio::Update(){
|
||||
if(Self().playBGMWaitTime>0.f){
|
||||
Self().playBGMWaitTime=std::max(Self().playBGMWaitTime-game->GetElapsedTime(),0.f);
|
||||
if(Self().playBGMWaitTime==0.f&&Self().immediatelyLoadAudio){
|
||||
while(!Self().BGMFullyLoaded()){
|
||||
UpdateLoop(); //We immediately load the file. In a loading screen setting we would defer UpdateLoop() such that we have extra time to update the screen, UpdateLoop() is divided into many parts of the music loading process.
|
||||
}
|
||||
}
|
||||
}
|
||||
if(Self().fadeToTargetVolumeTime>0.f){
|
||||
Self().fadeToTargetVolumeTime=std::max(0.f,Self().fadeToTargetVolumeTime-game->GetElapsedTime());
|
||||
for(int counter=0;float&vol:Self().prevVolumes){
|
||||
|
@ -56,10 +56,13 @@ public:
|
||||
static MiniAudio&Engine();
|
||||
static void Initialize();
|
||||
static void Update();
|
||||
static void UpdateLoop();
|
||||
static void Play(const std::string_view sound);
|
||||
[[nodiscard]]
|
||||
static const size_t LoadAndPlay(const std::string_view sound,const bool loop=true);
|
||||
//Play a BGM given a name found in bgm.txt configuration file.
|
||||
//Prepares a BGM for loading. This means we call UpdateLoop() repeatedly until the loading of the music is complete. Names are found in bgm.txt configuration file.
|
||||
static void PrepareBGM(const std::string_view sound,const bool loop=true);
|
||||
//Play immediately 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();
|
||||
@ -73,6 +76,14 @@ public:
|
||||
static float&GetSFXVolume();
|
||||
static float GetMuteMult();
|
||||
private:
|
||||
bool trackLoadStarted=false;
|
||||
bool trackLoadComplete=false;
|
||||
bool channelPlayingStarted=false;
|
||||
bool channelPlayingComplete=false;
|
||||
int currentLoopIndex=0;
|
||||
//Set to false by PrepareBGM(). If PlayBGM() is called instead, it will set the state of this variable to true, such that the loading is performed in Audio::Update()!
|
||||
bool immediatelyLoadAudio=false;
|
||||
|
||||
struct BGMPlayParams{
|
||||
std::string sound;
|
||||
bool loop;
|
||||
@ -92,7 +103,7 @@ private:
|
||||
const size_t GetChannelCount()const;
|
||||
const std::vector<ChannelName>&GetChannels()const;
|
||||
const SongName&GetName()const;
|
||||
const Volume&GetVolume(const Event&eventName,const ChannelID&id)const;
|
||||
const Volume&GetVolume(const Event&eventName,const int&index)const;
|
||||
void SetName(std::string_view name);
|
||||
void SetFileName(std::string_view name);
|
||||
void AddChannel(const ChannelName&name);
|
||||
|
@ -45,10 +45,14 @@ INCLUDE_WINDOW_SIZE
|
||||
bool LoadingScreen::loading=false;
|
||||
int LoadingScreen::totalProgress=0;
|
||||
int LoadingScreen::currentProgress=0;
|
||||
float LoadingScreen::waitTime=0.01f;
|
||||
|
||||
void LoadingScreen::DeferLoad(float waitTime){
|
||||
|
||||
}
|
||||
|
||||
void LoadingScreen::Update(){
|
||||
if(loading){
|
||||
|
||||
}
|
||||
}
|
||||
void LoadingScreen::Draw(){
|
||||
|
@ -42,6 +42,8 @@ public:
|
||||
static bool loading;
|
||||
static int totalProgress;
|
||||
static int currentProgress;
|
||||
static float waitTime;
|
||||
static void Update();
|
||||
static void Draw();
|
||||
static void DeferLoad(float waitTime);
|
||||
};
|
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 3
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 7521
|
||||
#define VERSION_BUILD 7526
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user