/********************************************************************* * \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; } } }