134 lines
3.7 KiB
C++
134 lines
3.7 KiB
C++
|
/*********************************************************************
|
||
|
* \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 <chrono>
|
||
|
#include <cassert>
|
||
|
#include <SHpch.h>
|
||
|
#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<double> 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;
|
||
|
}
|
||
|
}
|
||
|
}
|