Add loading screen. Added flag for music change parameter when loading levels. Release Build 7558.

pull/35/head
sigonasr2 9 months ago
parent 76c1487871
commit 0861419582
  1. 98
      Adventures in Lestoria/AdventuresInLestoria.cpp
  2. 8
      Adventures in Lestoria/AdventuresInLestoria.h
  3. 27
      Adventures in Lestoria/Audio.cpp
  4. 2
      Adventures in Lestoria/Audio.h
  5. 1
      Adventures in Lestoria/GameState.h
  6. 56
      Adventures in Lestoria/LoadingScreen.cpp
  7. 12
      Adventures in Lestoria/LoadingScreen.h
  8. 2
      Adventures in Lestoria/State_GameHub.cpp
  9. 1
      Adventures in Lestoria/State_GameHub.h
  10. 1
      Adventures in Lestoria/State_GameRun.cpp
  11. 1
      Adventures in Lestoria/State_GameRun.h
  12. 1
      Adventures in Lestoria/State_LevelComplete.cpp
  13. 1
      Adventures in Lestoria/State_LevelComplete.h
  14. 1
      Adventures in Lestoria/State_MainMenu.cpp
  15. 1
      Adventures in Lestoria/State_MainMenu.h
  16. 4
      Adventures in Lestoria/State_OverworldMap.cpp
  17. 1
      Adventures in Lestoria/State_OverworldMap.h
  18. 1
      Adventures in Lestoria/State_Story.cpp
  19. 1
      Adventures in Lestoria/State_Story.h
  20. 2
      Adventures in Lestoria/Version.h
  21. BIN
      x64/Release/Adventures in Lestoria.exe

@ -279,7 +279,7 @@ bool AiL::OnUserCreate(){
Inventory::AddItem("Minor Health Potion"s,3); Inventory::AddItem("Minor Health Potion"s,3);
Inventory::AddItem("Bandages"s,10); Inventory::AddItem("Bandages"s,10);
LoadLevel("starting_map"_S); LoadLevel("starting_map"_S,NO_MUSIC_CHANGE);
ChangePlayerClass(WARRIOR); ChangePlayerClass(WARRIOR);
GameState::Initialize(); GameState::Initialize();
@ -1821,14 +1821,22 @@ void AiL::InitializeLevel(std::string mapFile,MapName map){
} }
} }
void AiL::LoadLevel(MapName map){ void AiL::LoadLevel(MapName map,MusicChange changeMusic){
LoadingScreen::loading=true; LoadingScreen::loading=true;
_PrepareLevel(map,changeMusic);
}
void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
LoadingScreen::Reset();
previousLevel=currentLevel;
currentLevel=map;
#pragma region Reset all data (Loading phase 1) #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)); LoadingScreen::AddPhase([&](){
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!"); if(game->MAP_DATA.count(GetCurrentLevel())==0)ERR(std::format("WARNING! Could not load map {}! Does not exist! Refer to levels.txt for valid maps.",map));
if(game->MAP_DATA[GetCurrentLevel()].GetMapType()=="Hub"&&GameState::STATE!=GameState::states[States::GAME_HUB])ERR("WARNING! A hub level should only be initiated in the GAME_HUB game state!");
#pragma region Reset Environmental Audio #pragma region Reset Environmental Audio
for(EnvironmentalAudio&audio:MAP_DATA[GetCurrentLevel()].environmentalAudioData){ for(EnvironmentalAudio&audio:MAP_DATA[previousLevel].environmentalAudioData){
audio.Deactivate(); audio.Deactivate();
} }
#pragma endregion #pragma endregion
@ -1842,7 +1850,6 @@ void AiL::LoadLevel(MapName map){
GameEvent::events.clear(); GameEvent::events.clear();
worldColor=WHITE; worldColor=WHITE;
worldColorFunc=[&](vi2d pos){return game->worldColor;}; worldColorFunc=[&](vi2d pos){return game->worldColor;};
currentLevel=map;
levelTime=0; levelTime=0;
bossName=""; bossName="";
encounterDuration=0; encounterDuration=0;
@ -1858,13 +1865,15 @@ void AiL::LoadLevel(MapName map){
GetPlayer()->GetCastInfo()={}; GetPlayer()->GetCastInfo()={};
GetPlayer()->ResetAccumulatedXP(); GetPlayer()->ResetAccumulatedXP();
#pragma endregion
ZONE_LIST=game->MAP_DATA[game->GetCurrentLevel()].ZoneData; ZONE_LIST=game->MAP_DATA[game->GetCurrentLevel()].ZoneData;
return true;
});
#pragma endregion
#pragma region Monster Spawn Data Setup (Loading phase 2) #pragma region Monster Spawn Data Setup (Loading phase 2)
for(auto&[key,value]:MAP_DATA[map].SpawnerData){ LoadingScreen::AddPhase([&](){
SpawnerTag&spawnData=MAP_DATA[map].SpawnerData[key]; for(auto&[key,value]:MAP_DATA[GetCurrentLevel()].SpawnerData){
SpawnerTag&spawnData=MAP_DATA[GetCurrentLevel()].SpawnerData[key];
std::vector<std::pair<std::string,vf2d>>monster_list; std::vector<std::pair<std::string,vf2d>>monster_list;
vf2d spawnerRadius=vf2d{spawnData.ObjectData.GetFloat("width"),spawnData.ObjectData.GetFloat("height")}/2; vf2d spawnerRadius=vf2d{spawnData.ObjectData.GetFloat("width"),spawnData.ObjectData.GetFloat("height")}/2;
@ -1874,11 +1883,14 @@ void AiL::LoadLevel(MapName map){
} }
SPAWNER_LIST.push_back(MonsterSpawner{{spawnData.ObjectData.GetFloat("x"),spawnData.ObjectData.GetFloat("y")},spawnerRadius*2,monster_list,spawnData.upperLevel,spawnData.bossNameDisplay}); SPAWNER_LIST.push_back(MonsterSpawner{{spawnData.ObjectData.GetFloat("x"),spawnData.ObjectData.GetFloat("y")},spawnerRadius*2,monster_list,spawnData.upperLevel,spawnData.bossNameDisplay});
} }
return true;
});
#pragma endregion #pragma endregion
#pragma region Identify Upper Foreground Tiles (Loading phase 3) #pragma region Identify Upper Foreground Tiles (Loading phase 3)
LoadingScreen::AddPhase([&](){
auto GetUpperZones=[&](){ auto GetUpperZones=[&](){
for(auto&zoneSet:MAP_DATA[map].ZoneData){ for(auto&zoneSet:MAP_DATA[GetCurrentLevel()].ZoneData){
if(zoneSet.first=="UpperZone"){ //We are interested in all upper zones. if(zoneSet.first=="UpperZone"){ //We are interested in all upper zones.
return zoneSet.second; return zoneSet.second;
} }
@ -1892,7 +1904,7 @@ void AiL::LoadLevel(MapName map){
int zoneH=zone.zone.bottom().start.y/game->GetCurrentMapData().tilewidth-zoneY; int zoneH=zone.zone.bottom().start.y/game->GetCurrentMapData().tilewidth-zoneY;
for(int x=zoneX;x<zoneX+zoneW;x++){ for(int x=zoneX;x<zoneX+zoneW;x++){
for(int y=zoneY;y<zoneY+zoneH;y++){ for(int y=zoneY;y<zoneY+zoneH;y++){
for(LayerTag&layer:MAP_DATA[map].LayerData){ for(LayerTag&layer:MAP_DATA[GetCurrentLevel()].LayerData){
int tile=layer.tiles[y][x]-1; int tile=layer.tiles[y][x]-1;
TilesheetData tileSheet=GetTileSheet(currentLevel,tile); TilesheetData tileSheet=GetTileSheet(currentLevel,tile);
int tileSheetIndex=tile-(tileSheet.firstgid-1); int tileSheetIndex=tile-(tileSheet.firstgid-1);
@ -1903,9 +1915,12 @@ void AiL::LoadLevel(MapName map){
} }
} }
} }
return true;
});
#pragma endregion #pragma endregion
#pragma region Foreground and Upper Foreground Tile Fade Group Setup (Loading phase 4) #pragma region Foreground and Upper Foreground Tile Fade Group Setup (Loading phase 4)
LoadingScreen::AddPhase([&](){
std::set<vi2d>foregroundTilesAdded,upperForegroundTilesAdded; std::set<vi2d>foregroundTilesAdded,upperForegroundTilesAdded;
for(int x=0;x<GetCurrentMapData().width;x++){ for(int x=0;x<GetCurrentMapData().width;x++){
for(int y=0;y<GetCurrentMapData().height;y++){ for(int y=0;y<GetCurrentMapData().height;y++){
@ -1993,9 +2008,12 @@ void AiL::LoadLevel(MapName map){
for(TileGroup&group:upperForegroundTileGroups){ for(TileGroup&group:upperForegroundTileGroups){
std::sort(group.GetTiles().begin(),group.GetTiles().end(),[](TileRenderData&t1,TileRenderData&t2){return t1.layerID<t2.layerID;}); std::sort(group.GetTiles().begin(),group.GetTiles().end(),[](TileRenderData&t1,TileRenderData&t2){return t1.layerID<t2.layerID;});
} }
return true;
});
#pragma endregion #pragma endregion
#pragma region Foreground and Upper Foreground Tile Fade Group Individual Object Grouping Splitting (Loading phase 5) #pragma region Foreground and Upper Foreground Tile Fade Group Individual Object Grouping Splitting (Loading phase 5)
LoadingScreen::AddPhase([&](){
auto SplitUp=[&](std::vector<TileGroup>&group){ auto SplitUp=[&](std::vector<TileGroup>&group){
std::multimap<vi2d,TileRenderData>data; std::multimap<vi2d,TileRenderData>data;
using TileDataGroup=std::multimap<vi2d,TileRenderData>; //See below. using TileDataGroup=std::multimap<vi2d,TileRenderData>; //See below.
@ -2060,19 +2078,25 @@ void AiL::LoadLevel(MapName map){
}; };
SplitUp(foregroundTileGroups); SplitUp(foregroundTileGroups);
SplitUp(upperForegroundTileGroups); SplitUp(upperForegroundTileGroups);
return true;
});
#pragma endregion #pragma endregion
#pragma region Bridge Layer Setup (Loading Phase 6) #pragma region Bridge Layer Setup (Loading Phase 6)
LoadingScreen::AddPhase([&](){
bridgeLayerIndex=-1; bridgeLayerIndex=-1;
for(int counter=0;LayerTag&layer:MAP_DATA[map].LayerData){ for(int counter=0;LayerTag&layer:MAP_DATA[GetCurrentLevel()].LayerData){
if(IsBridgeLayer(layer)){ if(IsBridgeLayer(layer)){
bridgeLayerIndex=counter; bridgeLayerIndex=counter;
} }
counter++; counter++;
} }
return true;
});
#pragma endregion #pragma endregion
#pragma region Setup NPCs (Loading Phase 7) #pragma region Setup NPCs (Loading Phase 7)
LoadingScreen::AddPhase([&](){
for(NPCData data:game->MAP_DATA[game->GetCurrentLevel()].npcs){ for(NPCData data:game->MAP_DATA[game->GetCurrentLevel()].npcs){
if(Unlock::IsUnlocked(data.unlockCondition)){ if(Unlock::IsUnlocked(data.unlockCondition)){
MONSTER_LIST.push_back(Monster{data.spawnPos,MONSTER_DATA[data.name]}); MONSTER_LIST.push_back(Monster{data.spawnPos,MONSTER_DATA[data.name]});
@ -2080,9 +2104,12 @@ void AiL::LoadLevel(MapName map){
MONSTER_LIST.back().npcData=data; MONSTER_LIST.back().npcData=data;
} }
} }
return true;
});
#pragma endregion #pragma endregion
#pragma region Setup Player and Camera (Loading Phase 8) #pragma region Setup Player and Camera (Loading Phase 8)
LoadingScreen::AddPhase([&](){
player->GetAbility1().cooldown=0.f; player->GetAbility1().cooldown=0.f;
player->GetAbility2().cooldown=0.f; player->GetAbility2().cooldown=0.f;
player->GetAbility3().cooldown=0.f; player->GetAbility3().cooldown=0.f;
@ -2093,23 +2120,54 @@ void AiL::LoadLevel(MapName map){
player->useItem3.cooldown=0.f; player->useItem3.cooldown=0.f;
player->upperLevel=false; //Assume player starts on lower level. player->upperLevel=false; //Assume player starts on lower level.
player->ForceSetPos(MAP_DATA[map].MapData.playerSpawnLocation); //Normal set pos does one axis and then the other, so this will make sure that we actually end up at the right spot and ignore collision rules. player->ForceSetPos(MAP_DATA[GetCurrentLevel()].MapData.playerSpawnLocation); //Normal set pos does one axis and then the other, so this will make sure that we actually end up at the right spot and ignore collision rules.
vf2d cameraStartPos=player->GetPos()+vf2d(-24*6,0); vf2d cameraStartPos=player->GetPos()+vf2d(-24*6,0);
camera.MoveCamera(cameraStartPos); camera.MoveCamera(cameraStartPos);
return true;
});
#pragma endregion #pragma endregion
#pragma region Setup Pathfinding (Loading Phase 9) #pragma region Setup Pathfinding (Loading Phase 9)
LoadingScreen::AddPhase([&](){
pathfinder.Initialize(); pathfinder.Initialize();
return true;
});
#pragma endregion #pragma endregion
if(changeMusic==PLAY_LEVEL_MUSIC){
#pragma region Audio Preparation (Loading Phase 10)
LoadingScreen::AddPhase([&](){
Audio::SetAudioEvent("Default Volume"); 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. 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){ if(MAP_DATA[GetCurrentLevel()].bgmSongName.length()>0){
Audio::PlayBGM(MAP_DATA[map].bgmSongName); Audio::PrepareBGM(MAP_DATA[GetCurrentLevel()].bgmSongName);
DisableFadeIn(true); DisableFadeIn(true);
} }
LoadingScreen::loading=false; return true;
});
#pragma endregion
//Until the audio has stopped (by waiting for a set amount of time), we will respect the audio engine's wishes and not proceed.
LoadingScreen::DeferLoad([&](){return audioEngine.playBGMWaitTime==0.f;}); //This is the wait time for the audio engine to finish.
#pragma region Audio Channel Loading (Count based on Audio::GetPrepareBGMLoopIterations)
for(int i=0;i<Audio::GetPrepareBGMLoopIterations(MAP_DATA[GetCurrentLevel()].bgmSongName);i++){
LoadingScreen::AddPhase([&](){
Audio::UpdateLoop();
return true;
});
}
#pragma endregion
LoadingScreen::AddPhase([&](){
Audio::BGM&track=audioEngine.bgm[audioEngine.GetTrackName()];
for(int trackID:track.GetChannelIDs()){
audioEngine.Engine().Play(trackID,true);
}
return true;
});
}
} }
bool AiL::IsUpperForegroundTile(int tileID){ bool AiL::IsUpperForegroundTile(int tileID){
@ -3113,7 +3171,7 @@ void AiL::RenderFadeout(){
} }
bool AiL::GamePaused(){ bool AiL::GamePaused(){
return fadeOutDuration>0||disableFadeIn||paused; return fadeOutDuration>0||disableFadeIn||paused||LoadingScreen::loading;
} }
void AiL::PauseGame(){ void AiL::PauseGame(){
@ -3351,9 +3409,9 @@ const bool AiL::GameInitialized()const {
rcode AiL::LoadResource(Renderable&renderable,std::string_view imgPath,bool filter,bool clamp){ rcode AiL::LoadResource(Renderable&renderable,std::string_view imgPath,bool filter,bool clamp){
rcode returnCode; rcode returnCode;
if(gamepack.Loaded()){ if(gamepack.Loaded()){
returnCode=renderable.Load(std::string(imgPath),&gamepack); returnCode=renderable.Load(std::string(imgPath),&gamepack,filter,clamp);
}else{ }else{
returnCode=renderable.Load(std::string(imgPath)); returnCode=renderable.Load(std::string(imgPath),nullptr,filter,clamp);
if("GENERATE_GAMEPACK"_B){ if("GENERATE_GAMEPACK"_B){
gamepack.AddFile(std::string(imgPath)); gamepack.AddFile(std::string(imgPath));
} }

@ -72,6 +72,10 @@ class AiL : public olc::PixelGameEngine
std::unique_ptr<Player>player; std::unique_ptr<Player>player;
SplashScreen splash; SplashScreen splash;
public: public:
enum MusicChange{
NO_MUSIC_CHANGE,
PLAY_LEVEL_MUSIC,
};
Pathfinding pathfinder; Pathfinding pathfinder;
static InputGroup KEY_BACK; static InputGroup KEY_BACK;
static InputGroup KEY_CONFIRM; static InputGroup KEY_CONFIRM;
@ -127,6 +131,7 @@ private:
float lastWorldShakeAdjust=0; float lastWorldShakeAdjust=0;
vf2d worldShakeVel={}; vf2d worldShakeVel={};
const float WORLD_SHAKE_ADJUST_MAX_TIME=0.4f; const float WORLD_SHAKE_ADJUST_MAX_TIME=0.4f;
MapName previousLevel="CAMPAIGN_1_1";
MapName currentLevel="CAMPAIGN_1_1"; MapName currentLevel="CAMPAIGN_1_1";
std::vector<TileGroup>foregroundTileGroups; std::vector<TileGroup>foregroundTileGroups;
std::vector<TileGroup>upperForegroundTileGroups; std::vector<TileGroup>upperForegroundTileGroups;
@ -169,6 +174,7 @@ private:
ResourcePack gamepack; ResourcePack gamepack;
void ValidateGameStatus(); void ValidateGameStatus();
void _PrepareLevel(MapName map,MusicChange changeMusic);
#ifndef __EMSCRIPTEN__ #ifndef __EMSCRIPTEN__
::discord::Result SetupDiscord(); ::discord::Result SetupDiscord();
#endif #endif
@ -186,7 +192,7 @@ public:
geom2d::rect<float>NO_COLLISION={{0.f,0.f,},{0.f,0.f}}; geom2d::rect<float>NO_COLLISION={{0.f,0.f,},{0.f,0.f}};
TileTransformedView view; TileTransformedView view;
void InitializeLevel(std::string mapFile,MapName map); void InitializeLevel(std::string mapFile,MapName map);
void LoadLevel(MapName map); void LoadLevel(MapName map,MusicChange changeMusic=PLAY_LEVEL_MUSIC);
void HandleUserInput(float fElapsedTime); void HandleUserInput(float fElapsedTime);
void UpdateCamera(float fElapsedTime); void UpdateCamera(float fElapsedTime);
void UpdateEffects(float fElapsedTime); void UpdateEffects(float fElapsedTime);

@ -160,12 +160,16 @@ void Audio::BGM::Load(){
if(!Self().trackLoadStarted){ if(!Self().trackLoadStarted){
Self().trackLoadStarted=true; Self().trackLoadStarted=true;
if(Self().BGMIsPlaying()){ if(Self().BGMIsPlaying()){
if(Self().GetTrackName()==songFileName)return; //We are already playing the current track. if(Self().GetTrackName()==songFileName){ //We are already playing the current track.
Self().trackLoadComplete=Self().channelPlayingComplete=Self().fullyLoaded=true;
return;
}else{
BGM&bgm=Self().bgm[Self().GetTrackName()]; BGM&bgm=Self().bgm[Self().GetTrackName()];
if(Self().BGMIsPlaying()){ if(Self().BGMIsPlaying()){
bgm.Unload(); bgm.Unload();
} }
} }
}
Self().currentBGM=songFileName; Self().currentBGM=songFileName;
Self().currentLoopIndex=0; Self().currentLoopIndex=0;
BGM&newBgm=Self().bgm[songFileName]; BGM&newBgm=Self().bgm[songFileName];
@ -290,22 +294,22 @@ void Audio::UpdateLoop(){
Self().currentLoopIndex=0; Self().currentLoopIndex=0;
Self().channelPlayingStarted=true; Self().channelPlayingStarted=true;
}else{ }else{
int trackID=track.GetChannelIDs()[Self().currentLoopIndex]; int trackID=track.GetChannelIDs()[Self().currentLoopIndex];
float channelVol=track.GetVolume(Self().currentAudioEvent,Self().currentLoopIndex); float channelVol=track.GetVolume(Self().currentAudioEvent,Self().currentLoopIndex);
Self().prevVolumes.push_back(channelVol); Self().prevVolumes.push_back(channelVol);
Self().targetVolumes.push_back(channelVol); Self().targetVolumes.push_back(channelVol);
Engine().SetVolume(trackID,channelVol*GetBGMVolume()); Engine().SetVolume(trackID,channelVol*GetBGMVolume());
Engine().Play(trackID,Self().playParams.loop);
#pragma region Handle threaded loop indexing #pragma region Handle threaded loop indexing
Self().currentLoopIndex++; Self().currentLoopIndex++;
if(Self().currentLoopIndex>=track.GetChannelIDs().size()){ if(Self().currentLoopIndex>=track.GetChannelIDs().size()){
Self().channelPlayingComplete=true; Self().channelPlayingComplete=true;
Self().fullyLoaded=true;
} }
#pragma endregion #pragma endregion
} }
}else{ }else
Self().fullyLoaded=true; if(!Self().fullyLoaded){
ERR("Invalid loading state or too many calls to initialize audio loop! The audio is still not fully loaded!");
} }
} }
} }
@ -316,12 +320,18 @@ void Audio::PlayBGM(const std::string_view sound,const bool loop){
} }
void Audio::Update(){ void Audio::Update(){
if(Self().playBGMWaitTime>0.f){ if(Self().fadeToTargetVolumeTime==0.f&&Self().playBGMWaitTime>0.f){
Self().playBGMWaitTime=std::max(Self().playBGMWaitTime-game->GetElapsedTime(),0.f); Self().playBGMWaitTime=std::max(Self().playBGMWaitTime-game->GetElapsedTime(),0.f);
if(Self().playBGMWaitTime==0.f&&Self().immediatelyLoadAudio){ if(Self().playBGMWaitTime==0.f&&Self().immediatelyLoadAudio){
while(!Self().BGMFullyLoaded()){ 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. 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.
} }
//Start playing the tracks.
Audio::BGM&track=Self().bgm[Self().GetTrackName()];
for(int trackID:track.GetChannelIDs()){
Self().Engine().Play(trackID,true);
}
} }
} }
if(Self().fadeToTargetVolumeTime>0.f){ if(Self().fadeToTargetVolumeTime>0.f){
@ -364,3 +374,8 @@ float Audio::GetMuteMult(){
if(muted)return 0.f; if(muted)return 0.f;
return 1.f; return 1.f;
} }
int Audio::GetPrepareBGMLoopIterations(std::string_view sound){
BGM&newBgm=Self().bgm[std::string(sound)];
return newBgm.GetChannels().size()*2+2; //The channels list gets populated by calling newBgm.Load(), which then provides the list of channels that need to be loaded and played. This is why we multiply by 2. Each of the loading phases also consist of an initialization phase, so we add 2 as well.
}

@ -75,6 +75,8 @@ public:
static float&GetBGMVolume(); static float&GetBGMVolume();
static float&GetSFXVolume(); static float&GetSFXVolume();
static float GetMuteMult(); static float GetMuteMult();
//This will get a prepared BGM loop iteration count which is useful for loading stages.
static int GetPrepareBGMLoopIterations(std::string_view sound);
private: private:
bool trackLoadStarted=false; bool trackLoadStarted=false;
bool trackLoadComplete=false; bool trackLoadComplete=false;

@ -73,4 +73,5 @@ public:
virtual void GetAnyMousePress(int32_t mouseButton); virtual void GetAnyMousePress(int32_t mouseButton);
virtual void GetAnyMouseRelease(int32_t mouseButton); virtual void GetAnyMouseRelease(int32_t mouseButton);
static void ChangeState(States::State newState,float fadeOutDuration=0); static void ChangeState(States::State newState,float fadeOutDuration=0);
virtual void OnLevelLoad()=0;
}; };

@ -38,27 +38,71 @@ All rights reserved.
#include "AdventuresInLestoria.h" #include "AdventuresInLestoria.h"
#include "LoadingScreen.h" #include "LoadingScreen.h"
#include "util.h"
INCLUDE_game INCLUDE_game
INCLUDE_WINDOW_SIZE INCLUDE_WINDOW_SIZE
INCLUDE_ANIMATION_DATA
bool LoadingScreen::loading=false; bool LoadingScreen::loading=false;
int LoadingScreen::totalProgress=0;
int LoadingScreen::currentProgress=0; int LoadingScreen::currentProgress=0;
float LoadingScreen::waitTime=0.01f; int LoadingScreen::totalProgress=0;
std::queue<std::function<bool()>>LoadingScreen::loadingPhases;
void LoadingScreen::DeferLoad(float waitTime){ bool LoadingScreen::showGhost=false;
bool LoadingScreen::showLarge=false;
void LoadingScreen::DeferLoad(std::function<bool()>waitCondition){
AddPhase(waitCondition);
} }
void LoadingScreen::Update(){ void LoadingScreen::Update(){
if(loading){ if(loading){
if(loadingPhases.size()>0){
std::function<bool()>&loadFunc=loadingPhases.front();
if(loadFunc()){
currentProgress++;
loadingPhases.pop();
}
}else{
loading=false;
GameState::STATE->OnLevelLoad();
}
} }
} }
void LoadingScreen::Draw(){ void LoadingScreen::Draw(){
if(loading){ if(loading){
game->FillRectDecal({0,0},WINDOW_SIZE,VERY_DARK_GREEN); game->FillRectDecal({0,0},WINDOW_SIZE,{VERY_DARK_GREEN.r,VERY_DARK_GREEN.g,VERY_DARK_GREEN.b,230});
game->FillRectDecal({22.f,WINDOW_SIZE.y-46.f},{(float(currentProgress)/totalProgress)*(WINDOW_SIZE.x-48.f)+4.f,28.f},VERY_DARK_GREEN/2);
game->FillRectDecal({24.f,WINDOW_SIZE.y-48.f},{(float(currentProgress)/totalProgress)*(WINDOW_SIZE.x-48.f),24.f},DARK_YELLOW);
game->DrawShadowStringPropDecal({24.f,WINDOW_SIZE.y-60.f},"Loading...",{170,210,0},BLACK,{1.f,1.5f});
game->FillRectDecal({24.f,WINDOW_SIZE.y-48.f},{float(currentProgress/totalProgress)*WINDOW_SIZE.x-48,24.f},DARK_YELLOW); vf2d playerScale=vf2d(game->GetPlayer()->GetSizeMult(),game->GetPlayer()->GetSizeMult());
float scale=1.f;
if(showLarge){
scale=2.f;
} }
const std::vector<Buff>attackBuffs=game->GetPlayer()->GetStatBuffs({"Attack","Attack %"});
Pixel blendCol=attackBuffs.size()>0?Pixel{255,uint8_t(255*abs(sin(1.4*attackBuffs[0].duration))),uint8_t(255*abs(sin(1.4*attackBuffs[0].duration)))}:WHITE;
if(showGhost){
blendCol=BLACK;
}
game->GetPlayer()->GetWalkEAnimation();
Animate2D::FrameSequence&playerWalkE=ANIMATION_DATA[game->GetPlayer()->GetWalkEAnimation()];
game->DrawPartialRotatedDecal({(float(currentProgress)/totalProgress)*(WINDOW_SIZE.x-48.f),WINDOW_SIZE.y-36.f},playerWalkE.GetFrame(game->GetRuntime()).GetSourceImage()->Decal(),game->GetPlayer()->GetSpinAngle(),{12,12},playerWalkE.GetFrame(game->GetRuntime()).GetSourceRect().pos,playerWalkE.GetFrame(game->GetRuntime()).GetSourceRect().size,playerScale*scale,blendCol);
}
}
void LoadingScreen::Reset(){
currentProgress=0;
totalProgress=0;
showGhost=util::random()%6==0;
showLarge=util::random()%6==0;
while(loadingPhases.size()>0)ERR("WARNING! Previous loading phase was not properly cleared! This probably means some part of a previous load did not execute!");
}
void LoadingScreen::AddPhase(std::function<bool()>loadFunc){
loadingPhases.push(loadFunc);
totalProgress++;
} }

@ -37,13 +37,21 @@ All rights reserved.
#pragma endregion #pragma endregion
#pragma once #pragma once
#include <queue>
#include "olcUTIL_Animate2D.h"
class LoadingScreen{ class LoadingScreen{
public: public:
static bool loading; static bool loading;
static int totalProgress;
static int currentProgress; static int currentProgress;
static int totalProgress;
static float waitTime; static float waitTime;
static bool showGhost;
static bool showLarge;
static std::queue<std::function<bool()>>loadingPhases;
static void Update(); static void Update();
static void Draw(); static void Draw();
static void DeferLoad(float waitTime); static void DeferLoad(std::function<bool()>waitCondition);
static void Reset();
static void AddPhase(std::function<bool()>loadFunc);
}; };

@ -59,6 +59,8 @@ void State_GameHub::OnStateChange(GameState*prevState){
game->GetPlayer()->SetState(State::NORMAL); game->GetPlayer()->SetState(State::NORMAL);
game->LoadLevel("HUB"); game->LoadLevel("HUB");
}
void State_GameHub::OnLevelLoad(){
game->UpdateDiscordStatus("Hub Area",game->GetPlayer()->GetClassName()); game->UpdateDiscordStatus("Hub Area",game->GetPlayer()->GetClassName());
} }
void State_GameHub::OnUserUpdate(AiL*game){ void State_GameHub::OnUserUpdate(AiL*game){

@ -45,4 +45,5 @@ class State_GameHub:public State_GameRun{
virtual void OnStateChange(GameState*prevState)override final; virtual void OnStateChange(GameState*prevState)override final;
virtual void OnUserUpdate(AiL*game)override final; virtual void OnUserUpdate(AiL*game)override final;
virtual void Draw(AiL*game)override final; virtual void Draw(AiL*game)override final;
virtual void OnLevelLoad()override final;
}; };

@ -73,6 +73,7 @@ void State_GameRun::OnStateChange(GameState*prevState){
game->LoadLevel(State_OverworldMap::GetCurrentConnectionPoint().map); game->LoadLevel(State_OverworldMap::GetCurrentConnectionPoint().map);
} }
void State_GameRun::OnLevelLoad(){}
void State_GameRun::OnUserUpdate(AiL*game){ void State_GameRun::OnUserUpdate(AiL*game){
game->bossDisplayTimer=std::max(0.f,game->bossDisplayTimer-game->GetElapsedTime()); game->bossDisplayTimer=std::max(0.f,game->bossDisplayTimer-game->GetElapsedTime());
if(game->encounterStarted&&game->totalBossEncounterMobs>0){ if(game->encounterStarted&&game->totalBossEncounterMobs>0){

@ -46,6 +46,7 @@ protected:
virtual void OnStateChange(GameState*prevState)override; virtual void OnStateChange(GameState*prevState)override;
virtual void OnUserUpdate(AiL*game)override; virtual void OnUserUpdate(AiL*game)override;
virtual void Draw(AiL*game)override; virtual void Draw(AiL*game)override;
virtual void OnLevelLoad()override;
void FontTest(); void FontTest();
void FontSpriteTest(); void FontSpriteTest();
}; };

@ -76,6 +76,7 @@ void State_LevelComplete::OnStateChange(GameState*prevState){
game->GetPlayer()->SetState(State::NORMAL); game->GetPlayer()->SetState(State::NORMAL);
Menu::OpenMenu(LEVEL_COMPLETE); Menu::OpenMenu(LEVEL_COMPLETE);
}; };
void State_LevelComplete::OnLevelLoad(){}
void State_LevelComplete::OnUserUpdate(AiL*game){ void State_LevelComplete::OnUserUpdate(AiL*game){
if(levelUpTimer>0.f){ if(levelUpTimer>0.f){
levelUpTimer=std::max(0.f,levelUpTimer-game->GetElapsedTime()); levelUpTimer=std::max(0.f,levelUpTimer-game->GetElapsedTime());

@ -48,4 +48,5 @@ class State_LevelComplete:public GameState{
virtual void OnUserUpdate(AiL*game)override final; virtual void OnUserUpdate(AiL*game)override final;
virtual void Draw(AiL*game)override final; virtual void Draw(AiL*game)override final;
virtual void DrawOverlay(AiL*game)override final; virtual void DrawOverlay(AiL*game)override final;
virtual void OnLevelLoad()override final;
}; };

@ -48,6 +48,7 @@ void State_MainMenu::OnStateChange(GameState*prevState){
TitleScreen::Reset(); TitleScreen::Reset();
game->UpdateDiscordStatus("Main Menu",""); game->UpdateDiscordStatus("Main Menu","");
}; };
void State_MainMenu::OnLevelLoad(){}
void State_MainMenu::OnUserUpdate(AiL*game){ void State_MainMenu::OnUserUpdate(AiL*game){
TitleScreen::Update(); TitleScreen::Update();
if(AiL::KEY_CONFIRM.Released()){ if(AiL::KEY_CONFIRM.Released()){

@ -41,4 +41,5 @@ class State_MainMenu:public GameState{
virtual void OnStateChange(GameState*prevState)override final; virtual void OnStateChange(GameState*prevState)override final;
virtual void OnUserUpdate(AiL*game)override final; virtual void OnUserUpdate(AiL*game)override final;
virtual void Draw(AiL*game)override final; virtual void Draw(AiL*game)override final;
virtual void OnLevelLoad()override final;
}; };

@ -63,6 +63,8 @@ void State_OverworldMap::OnStateChange(GameState*prevState){
Component<MenuComponent>(MenuType::PAUSE,"Return to Camp Button")->SetGrayedOut(false); Component<MenuComponent>(MenuType::PAUSE,"Return to Camp Button")->SetGrayedOut(false);
SaveFile::SaveGame(); SaveFile::SaveGame();
game->LoadLevel("WORLD_MAP"); game->LoadLevel("WORLD_MAP");
};
void State_OverworldMap::OnLevelLoad(){
if(Menu::IsMenuOpen()){ if(Menu::IsMenuOpen()){
Menu::CloseAllMenus(); Menu::CloseAllMenus();
} }
@ -82,7 +84,7 @@ void State_OverworldMap::OnStateChange(GameState*prevState){
} }
Menu::OpenMenu(OVERWORLD_LEVEL_SELECT,false); Menu::OpenMenu(OVERWORLD_LEVEL_SELECT,false);
game->UpdateDiscordStatus("Overworld Map",game->GetPlayer()->GetClassName()); game->UpdateDiscordStatus("Overworld Map",game->GetPlayer()->GetClassName());
}; }
void State_OverworldMap::OnUserUpdate(AiL*game){ void State_OverworldMap::OnUserUpdate(AiL*game){
if(Menu::stack.size()>1)return; if(Menu::stack.size()>1)return;

@ -60,6 +60,7 @@ public:
virtual void OnUserUpdate(AiL*game)override final; virtual void OnUserUpdate(AiL*game)override final;
virtual void Draw(AiL*game)override final; virtual void Draw(AiL*game)override final;
virtual void DrawOverlay(AiL*game)override final; virtual void DrawOverlay(AiL*game)override final;
virtual void OnLevelLoad()override final;
static void StartLevel(); static void StartLevel();
static void UpdateCurrentConnectionPoint(const ConnectionPoint&connection); static void UpdateCurrentConnectionPoint(const ConnectionPoint&connection);
}; };

@ -42,6 +42,7 @@ All rights reserved.
void State_Story::OnStateChange(GameState*prevState){ void State_Story::OnStateChange(GameState*prevState){
Menu::CloseAllMenus(); Menu::CloseAllMenus();
}; };
void State_Story::OnLevelLoad(){}
void State_Story::OnUserUpdate(AiL*game){ void State_Story::OnUserUpdate(AiL*game){
VisualNovel::novel.Update(); VisualNovel::novel.Update();
}; };

@ -42,4 +42,5 @@ class State_Story:public GameState{
virtual void OnStateChange(GameState*prevState)override final; virtual void OnStateChange(GameState*prevState)override final;
virtual void OnUserUpdate(AiL*game)override final; virtual void OnUserUpdate(AiL*game)override final;
virtual void Draw(AiL*game)override final; virtual void Draw(AiL*game)override final;
virtual void OnLevelLoad()override final;
}; };

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 3 #define VERSION_MINOR 3
#define VERSION_PATCH 0 #define VERSION_PATCH 0
#define VERSION_BUILD 7526 #define VERSION_BUILD 7558
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

Loading…
Cancel
Save