diff --git a/SHADE_Engine/SHADE_Engine.vcxproj b/SHADE_Engine/SHADE_Engine.vcxproj index 7ccf0e8e..1149b571 100644 --- a/SHADE_Engine/SHADE_Engine.vcxproj +++ b/SHADE_Engine/SHADE_Engine.vcxproj @@ -123,6 +123,7 @@ + @@ -210,6 +211,7 @@ + diff --git a/SHADE_Engine/SHADE_Engine.vcxproj.filters b/SHADE_Engine/SHADE_Engine.vcxproj.filters index 1bbdea43..b2cc911f 100644 --- a/SHADE_Engine/SHADE_Engine.vcxproj.filters +++ b/SHADE_Engine/SHADE_Engine.vcxproj.filters @@ -387,6 +387,7 @@ Tools + @@ -591,5 +592,6 @@ Tools + \ No newline at end of file diff --git a/SHADE_Engine/src/FRC/SHFramerateController.cpp b/SHADE_Engine/src/FRC/SHFramerateController.cpp new file mode 100644 index 00000000..d64c6336 --- /dev/null +++ b/SHADE_Engine/src/FRC/SHFramerateController.cpp @@ -0,0 +1,134 @@ +/********************************************************************* + * \file SHFramerateController.cpp + * \author Ryan Wang Nian Jing + * \brief Definition for functions of the framerate controller + * Handles changing of scenes and manages loop (timestep, etc.) + * + * \copyright Copyright (c) 2022 DigiPen Institute of Technology. Reproduction + or disclosure of this file or its contents without the prior written + consent of DigiPen Institute of Technology is prohibited. + *********************************************************************/ + +#include +#include +#include +#include "SHFramerateController.h" +#include "../Tools/SHLogger.h" + +namespace SHADE +{ + //Init statics + double SHFramerateController::fixedTimestep = 0.01; + SHScene* SHFramerateController::previousScene = nullptr; + SHScene* SHFramerateController::currentScene = nullptr; + SHScene* SHFramerateController::nextScene = nullptr; + bool SHFramerateController::toRestart = false; + bool SHFramerateController::toQuit = false; + + //Scene manager loop + void SHFramerateController::Run(SHScene* firstScene) + { + if (firstScene == nullptr) + { + SHLOG_ERROR("Do not pass a nullptr as the firstScene"); + return; + } + + //Set quit and restart flags to false + toQuit = false; + toRestart = false; + + //Set the first scene to run + previousScene = firstScene; + currentScene = firstScene; + nextScene = firstScene; + + while (!toQuit) + { + if (toRestart) + { + //Restart current scene + currentScene = previousScene; + nextScene = previousScene; + toRestart = false; + } + else + { + //Move to a new scene + currentScene->Load(); + } + + //Call init function of current scene + currentScene->Init(); + + //Have an initial value + //This frame time will fluctuate + //SHOULD be larger than the fixed timestep + //TODO this might need to be changed + double variableLastFrameTime = fixedTimestep; + + //Time accumulator for meshing between fixed and variable timesteps + double accumulator = 0.0; + + //Start state loop + while (currentScene == nextScene && !toQuit && !toRestart) + { + //Use of new STL timing functions + //https://en.cppreference.com/w/cpp/chrono + std::chrono::duration deltaTime; + + auto startTime = std::chrono::high_resolution_clock::now(); + + //Whittle down the accumulator by continuously simulating + for (; accumulator > fixedTimestep; accumulator -= fixedTimestep) + { + MSG msg; + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + //TODO change to double + currentScene->Update((float)fixedTimestep); + } + + //Interpolation + //Manage the alpha value well + //https://randomascii.wordpress.com/2012/02/13/dont-store-that-in-a-float/ + //Key points: + //1) Any time you add or subtract floats of widely varying + // magnitudes, you need to watch for loss of precision + //2) Sometimes using double instead of float is the correct + // solution, but often a more stable algorithm is more important + //3) calcT() should probably use double (to give sufficient + // precision after many hours of gameplay) + + //TODO awaiting approval to use this + //double alpha = accumulator / fixedTimestep; + + //assert alpha does not go out of range + + currentScene->Render(); + + auto endTime = std::chrono::high_resolution_clock::now(); + deltaTime = endTime - startTime; + variableLastFrameTime = deltaTime.count(); + + //Increase accumulator + accumulator += variableLastFrameTime; + } + + //Free once out of scene loop + currentScene->Free(); + + //Check if not to restart state + //If so, unload + if (!toRestart) currentScene->Unload(); + + //Shift forward scenes + previousScene = currentScene; + currentScene = nextScene; + } + } +} \ No newline at end of file diff --git a/SHADE_Engine/src/FRC/SHFramerateController.h b/SHADE_Engine/src/FRC/SHFramerateController.h new file mode 100644 index 00000000..26f276d8 --- /dev/null +++ b/SHADE_Engine/src/FRC/SHFramerateController.h @@ -0,0 +1,62 @@ +/********************************************************************* + * \file SHFramerateController.h + * \author Ryan Wang Nian Jing + * \brief Declaration for the framerate controller + * Handles changing of scenes and manages loop (timestep, etc.) + * + * \copyright Copyright (c) 2022 DigiPen Institute of Technology. Reproduction + or disclosure of this file or its contents without the prior written + consent of DigiPen Institute of Technology is prohibited. + *********************************************************************/ + +#ifndef SH_FRAMERATECONTROLLER_H +#define SH_FRAMERATECONTROLLER_H +#pragma once + +#include "../Scene/SHScene.h" + +namespace SHADE +{ + class SHFramerateController + { + private: + //scene pointers + static SHScene* previousScene; + static SHScene* currentScene; + static SHScene* nextScene; + + //Flags + //Whether the flag has been raised for the game to be quit + static bool toQuit; + + //Whether the flag has been raised for the current scene to restart + static bool toRestart; + + public: + //Fixed timestep value for physics. Default at 1/100th of a second. + //Should be lower than the variable refresh rate + static double fixedTimestep; + + //Scene Manager Loop + //This loop is vital to the game because it runs for as long as the game + //runs. Before entering, initialise vital systems for game. After exiting, + //free these vital systems before finishing the main() function and + //terminating the game + //Parameter of firstScene is what scene the game should start with + static void Run(SHScene* firstScene); + + //Set the flag to restart the current game scene + static inline void RestartScene() { toRestart = true; } + + //Set the flag to halt running of the scene manager and quit the game + static inline void QuitGame() { toQuit = true; } + + //Set the next scene to be excuted + //This will tell the scene manager to + //halt execution of the current scene and prepare + //execution of the next + static inline void SetNextScene(SHScene* const next) { nextScene = next; } + }; +} + +#endif \ No newline at end of file