From 49289772632d4cc8d7ec6f05a2eda08aefa3f010 Mon Sep 17 00:00:00 2001 From: Julia Butenhoff Date: Sun, 24 Apr 2022 22:21:53 -0500 Subject: [PATCH] Prevent Start Button from Pressing While Transitioning --- Sonataria/GameState.cpp | 81 +++++++++++++++++++---- Sonataria/GameState.h | 15 ++++- Sonataria/Networking.cpp | 2 +- Sonataria/ScreenRenderer.cpp | 4 +- Sonataria/main.cpp | 125 ++++++++++++++++++----------------- 5 files changed, 147 insertions(+), 80 deletions(-) diff --git a/Sonataria/GameState.cpp b/Sonataria/GameState.cpp index 847c91d..028e3a6 100644 --- a/Sonataria/GameState.cpp +++ b/Sonataria/GameState.cpp @@ -9,7 +9,8 @@ GameState gameState; // Forward Declarations -void CurtainDelay(int); +void CurtainDelay(int, bool); +void GameStateChangeThread(GameState::CurrentState, GameState::CurrentState); /** * Default constructor. @@ -25,7 +26,8 @@ GameState::GameState() { this->speed = 0; // Value in Milliseconds - this->CurtainTransitionTime = 500; + this->CurtainTransitionTime = 1500; + this->isTransitioning = false; } /** @@ -49,32 +51,65 @@ GameState::CurrentState GameState::getGameState() { * @param newState the state to set the game state to */ void GameState::setGameState(GameState::CurrentState newState) { + // Prevent "T" presses while swapping game states + this->isTransitioning = true; + + // Launch a thread to prevent blocking + thread changeState; + changeState = std::thread(GameStateChangeThread, this->state, newState); + changeState.detach(); + + // We don't unlock the "T" key here + // It is unlocked in the launched thread so that it ensures the game state finished swapping +} + +void GameStateChangeThread(GameState::CurrentState oldState, GameState::CurrentState newState) { // Close Curtains - if (!(this->state == GameState::CurrentState::STARTUP) && !(newState == GameState::CurrentState::SHUTDOWN)) { + thread delay; + if (!gameState.isInServiceGameState() && !gameState.isInServiceGameState(newState)) { + // Begin Animation screenRenderer.ToggleCurtains(false); + + // Only add the delay if we actually transition + delay = std::thread(CurtainDelay, gameState.CurtainTransitionTime, true); + + // Wait for it to finish + delay.join(); } // Unload the State - this->onStateUnload(this->state); - - // Artificial Delay to allow curtains to close for transition - std::thread delay(CurtainDelay, this->CurtainTransitionTime); - delay.join(); + gameState.onStateUnload(oldState); // Switch the State - this->state = newState; + gameState.state = newState; // Handle loading the state - this->onStateLoad(newState); + gameState.onStateLoad(newState); // Open Curtains - if (!(newState == GameState::CurrentState::SHUTDOWN)) { + if (!gameState.isInServiceGameState() && !gameState.isInServiceGameState(newState)) { + // Begin Animation screenRenderer.ToggleCurtains(true); + + // Add the delay again to make sure the transition ends + delay = std::thread(CurtainDelay, gameState.CurtainTransitionTime, false); + + // Wait for it to finish + delay.join(); } + + // Allow "T" presses again + gameState.isTransitioning = false; } -void CurtainDelay(int mSec) { - std::this_thread::sleep_for(std::chrono::milliseconds(mSec + 1000)); +void CurtainDelay(int mSec, bool addExtraDelay) { + int totalTime = mSec; + + // Add extra time on the curtain close before reopening + if (addExtraDelay) { totalTime += 1000; } + + // Sleep the thread + std::this_thread::sleep_for(std::chrono::milliseconds(totalTime)); } /** @@ -234,4 +269,24 @@ string GameState::getOnlineStateStr() { default: return ""; } +} + +// Check if the current game state is one of the service states +bool GameState::isInServiceGameState() { + for (size_t i = 0; i < this->serviceStates.size(); i++) { + if (this->state == this->serviceStates[i]) { + return true; + } + } + return false; +} + +// Check if a specific game state is one of the service states +bool GameState::isInServiceGameState(CurrentState stateToCheck) { + for (size_t i = 0; i < this->serviceStates.size(); i++) { + if (stateToCheck == this->serviceStates[i]) { + return true; + } + } + return false; } \ No newline at end of file diff --git a/Sonataria/GameState.h b/Sonataria/GameState.h index e4066e5..f0c2b8f 100644 --- a/Sonataria/GameState.h +++ b/Sonataria/GameState.h @@ -45,17 +45,26 @@ class GameState { string getOnlineStateStr(); int CurtainTransitionTime; + bool isTransitioning; + bool isInServiceGameState(); + bool isInServiceGameState(CurrentState); + + void onStateUnload(CurrentState); + void onStateLoad(CurrentState); + + CurrentState state; private: - CurrentState state; OnlineState onlineState; int err_code; bool servicePressed; Song currentlyPlaying; int difficulty; int speed; - void onStateUnload(CurrentState); - void onStateLoad(CurrentState); + vector serviceStates{ + CurrentState::STARTUP, CurrentState::SHUTDOWN, CurrentState::ERROR_CODE, CurrentState::TEST_MENU_MAIN, + CurrentState::UPDATES, CurrentState::TEST_MENU_IOCHECK, CurrentState::TEST_MENU_INPUTCHECK, + CurrentState::TEST_MENU_SYSINFO, CurrentState::TEST_MENU_SOUNDOPTIONS, CurrentState::TEST_MENU_NETWORKING }; }; extern GameState gameState; \ No newline at end of file diff --git a/Sonataria/Networking.cpp b/Sonataria/Networking.cpp index bf7812f..f48d46c 100644 --- a/Sonataria/Networking.cpp +++ b/Sonataria/Networking.cpp @@ -29,7 +29,7 @@ const int PORT = 57015; */ Networking::Networking() { // Set the version of the game - this->version = "20220418-J-01"; + this->version = "20220424-J-01"; // Set the information for connecting to the server this->ServerAddress = "http://127.0.0.1:3000"; diff --git a/Sonataria/ScreenRenderer.cpp b/Sonataria/ScreenRenderer.cpp index a2dd58d..66408ad 100644 --- a/Sonataria/ScreenRenderer.cpp +++ b/Sonataria/ScreenRenderer.cpp @@ -467,8 +467,8 @@ void ScreenRenderer::render(sf::RenderWindow* gameWindow) { // DRAW BACKGROUNDS / STAGE (MAIN SET) { - if (gameState.getGameState() == GameState::CurrentState::STARTUP) { - // Don't render anything background related + if (gameState.isInServiceGameState()) { + // Don't render anything background related when in a service state } else if (gameState.getGameState() == GameState::CurrentState::TITLE_SCREEN) { titleScreen->render(PROJECTION::ORTHOGRAPHIC); diff --git a/Sonataria/main.cpp b/Sonataria/main.cpp index d159176..3df0ed1 100644 --- a/Sonataria/main.cpp +++ b/Sonataria/main.cpp @@ -206,8 +206,10 @@ int main(int argc, char** argv) { else if(evnt.key.code == sf::Keyboard::T) { controllerInput.setKeyState(6, true); PacSetLEDState(0, 3, true); - if (gameState.getGameState() == GameState::CurrentState::TEST_MENU_MAIN) { - switch (screenRenderer.getTestMenuPos()) { + // Only do actions if the game isn't doing the curtain transition effect + if (!gameState.isTransitioning) { + if (gameState.getGameState() == GameState::CurrentState::TEST_MENU_MAIN) { + switch (screenRenderer.getTestMenuPos()) { case 0: gameState.setGameState(GameState::CurrentState::TEST_MENU_IOCHECK); screenRenderer.testMenuReset(); @@ -228,10 +230,10 @@ int main(int argc, char** argv) { gameState.setGameState(GameState::CurrentState::TITLE_SCREEN); screenRenderer.testMenuReset(); break; + } } - } - else if (gameState.getGameState() == GameState::CurrentState::TEST_MENU_IOCHECK) { - switch (screenRenderer.getTestMenuIOCheckPos()) { + else if (gameState.getGameState() == GameState::CurrentState::TEST_MENU_IOCHECK) { + switch (screenRenderer.getTestMenuIOCheckPos()) { case 0: gameState.setGameState(GameState::CurrentState::TEST_MENU_INPUTCHECK); screenRenderer.testMenuReset(); @@ -240,18 +242,18 @@ int main(int argc, char** argv) { gameState.setGameState(GameState::CurrentState::TEST_MENU_MAIN); screenRenderer.testMenuReset(); break; + } } - } - else if (gameState.getGameState() == GameState::CurrentState::TEST_MENU_INPUTCHECK) { - gameState.setGameState(GameState::CurrentState::TEST_MENU_IOCHECK); - screenRenderer.testMenuReset(); - } - else if (gameState.getGameState() == GameState::CurrentState::TEST_MENU_SYSINFO) { - gameState.setGameState(GameState::CurrentState::TEST_MENU_MAIN); - screenRenderer.testMenuReset(); - } - else if (gameState.getGameState() == GameState::CurrentState::TEST_MENU_SOUNDOPTIONS) { - switch (screenRenderer.getTestMenuSoundOptionsPos()) { + else if (gameState.getGameState() == GameState::CurrentState::TEST_MENU_INPUTCHECK) { + gameState.setGameState(GameState::CurrentState::TEST_MENU_IOCHECK); + screenRenderer.testMenuReset(); + } + else if (gameState.getGameState() == GameState::CurrentState::TEST_MENU_SYSINFO) { + gameState.setGameState(GameState::CurrentState::TEST_MENU_MAIN); + screenRenderer.testMenuReset(); + } + else if (gameState.getGameState() == GameState::CurrentState::TEST_MENU_SOUNDOPTIONS) { + switch (screenRenderer.getTestMenuSoundOptionsPos()) { case 0: // System Volume if (screenRenderer.getTestMenuSoundOptionsSelected()) { screenRenderer.setTestMenuSoundOptionsSelected(false); @@ -264,26 +266,26 @@ int main(int argc, char** argv) { gameState.setGameState(GameState::CurrentState::TEST_MENU_MAIN); screenRenderer.testMenuReset(); break; + } } - } - else if (gameState.getGameState() == GameState::CurrentState::TEST_MENU_NETWORKING) { - int status = 0; - switch (screenRenderer.getTestMenuNetworkingPos()) { + else if (gameState.getGameState() == GameState::CurrentState::TEST_MENU_NETWORKING) { + int status = 0; + switch (screenRenderer.getTestMenuNetworkingPos()) { case 0: // Network check logger.log(L"Testing Network..."); screenRenderer.isNetworkChecking = true; status = network.checkConnection(); switch (status) { - case 1: - gameState.setOnlineState(GameState::OnlineState::ONLINE); - break; - case 2: - gameState.setOnlineState(GameState::OnlineState::OFFLINE); - break; - case 3: - gameState.setOnlineState(GameState::OnlineState::MAINTENENCE); - break; + case 1: + gameState.setOnlineState(GameState::OnlineState::ONLINE); + break; + case 2: + gameState.setOnlineState(GameState::OnlineState::OFFLINE); + break; + case 3: + gameState.setOnlineState(GameState::OnlineState::MAINTENENCE); + break; } screenRenderer.isNetworkChecking = false; logger.log(L"Network Test Finished."); @@ -292,42 +294,43 @@ int main(int argc, char** argv) { gameState.setGameState(GameState::CurrentState::TEST_MENU_MAIN); screenRenderer.testMenuReset(); break; + } } - } - else if (gameState.getGameState() == GameState::CurrentState::TITLE_SCREEN) { - RFIDCardReader::getCardReader()->clearLastCardData(); - gameState.setGameState(GameState::CurrentState::PRELOGIN); - controllerInput.reset(); - } - else if (gameState.getGameState() == GameState::CurrentState::PRELOGIN) { - // TODO: go to tutorial and such... - gameState.setGameState(GameState::CurrentState::SONG_SELECT); - controllerInput.reset(); - } - else if (gameState.getGameState() == GameState::CurrentState::SONG_SELECT) { - if (screenRenderer.isCurrentSongValidToPlay()) { - gameState.setSongPlaying(screenRenderer.currentPageSongs[screenRenderer.getSongSelectHoverOver()], screenRenderer.currentPageSongs[screenRenderer.getSongSelectHoverOver()].getDifficultyNumber(screenRenderer.getDifficultyHoverOver())); - gameState.setGameState(GameState::CurrentState::GAME); + else if (gameState.getGameState() == GameState::CurrentState::TITLE_SCREEN) { + RFIDCardReader::getCardReader()->clearLastCardData(); + gameState.setGameState(GameState::CurrentState::PRELOGIN); + controllerInput.reset(); } - else { - // TODO: Play the invalid selection sound effect - } - controllerInput.reset(); - } - else if (gameState.getGameState() == GameState::CurrentState::RESULTS) { - if (gameState.results.size() >= 2) { - // TODO: Check for EX Track then go to final results or ex track - gameState.setGameState(GameState::CurrentState::FINAL_RESULTS); - } - else { + else if (gameState.getGameState() == GameState::CurrentState::PRELOGIN) { + // TODO: go to tutorial and such... gameState.setGameState(GameState::CurrentState::SONG_SELECT); + controllerInput.reset(); + } + else if (gameState.getGameState() == GameState::CurrentState::SONG_SELECT) { + if (screenRenderer.isCurrentSongValidToPlay()) { + gameState.setSongPlaying(screenRenderer.currentPageSongs[screenRenderer.getSongSelectHoverOver()], screenRenderer.currentPageSongs[screenRenderer.getSongSelectHoverOver()].getDifficultyNumber(screenRenderer.getDifficultyHoverOver())); + gameState.setGameState(GameState::CurrentState::GAME); + } + else { + // TODO: Play the invalid selection sound effect + } + controllerInput.reset(); + } + else if (gameState.getGameState() == GameState::CurrentState::RESULTS) { + if (gameState.results.size() >= 2) { + // TODO: Check for EX Track then go to final results or ex track + gameState.setGameState(GameState::CurrentState::FINAL_RESULTS); + } + else { + gameState.setGameState(GameState::CurrentState::SONG_SELECT); + } + controllerInput.reset(); + } + else if (gameState.getGameState() == GameState::CurrentState::FINAL_RESULTS) { + gameState.setGameState(GameState::CurrentState::TITLE_SCREEN); + // Clear the saved data at the end of the credit regardless of whether or not they are carded in + userData.clearData(); } - controllerInput.reset(); - } - else if (gameState.getGameState() == GameState::CurrentState::FINAL_RESULTS) { - gameState.setGameState(GameState::CurrentState::TITLE_SCREEN); - // Clear the saved data at the end of the credit regardless of whether or not they are carded in - userData.clearData(); } } else if(evnt.key.code == sf::Keyboard::Escape) {