Merge pull request #18 from SHADE-DP/SP3-19-frame-rate-controller

FRC implemented
Handles the main game loop, which includes:

Handling restarting of scenes by freeing and initializing again
Handling changes of scenes by unloading previous scene and loading the next
Calling to update on a fixed time basis and reducing the accumulator
Calling to render on a variable time basis and adding to the accumulator
Measuring of variable time elapsed per frame
Ready for integration. Anticipating much change from this implementation during integration.
This commit is contained in:
XiaoQiDigipen 2022-09-15 11:34:53 +08:00 committed by GitHub
commit 5ebdf87714
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 200 additions and 0 deletions

View File

@ -123,6 +123,7 @@
<ClInclude Include="src\ECS_Base\System\SHSystemManager.h" /> <ClInclude Include="src\ECS_Base\System\SHSystemManager.h" />
<ClInclude Include="src\Engine\SHEngine.h" /> <ClInclude Include="src\Engine\SHEngine.h" />
<ClInclude Include="src\Filesystem\SHFileSystem.h" /> <ClInclude Include="src\Filesystem\SHFileSystem.h" />
<ClInclude Include="src\FRC\SHFramerateController.h" />
<ClInclude Include="src\Graphics\Buffers\SHVkBuffer.h" /> <ClInclude Include="src\Graphics\Buffers\SHVkBuffer.h" />
<ClInclude Include="src\Graphics\Commands\SHCommandPoolResetMode.h" /> <ClInclude Include="src\Graphics\Commands\SHCommandPoolResetMode.h" />
<ClInclude Include="src\Graphics\Commands\SHVkCommandBuffer.h" /> <ClInclude Include="src\Graphics\Commands\SHVkCommandBuffer.h" />
@ -210,6 +211,7 @@
<ClCompile Include="src\ECS_Base\System\SHSystemManager.cpp" /> <ClCompile Include="src\ECS_Base\System\SHSystemManager.cpp" />
<ClCompile Include="src\Engine\SHEngine.cpp" /> <ClCompile Include="src\Engine\SHEngine.cpp" />
<ClCompile Include="src\Filesystem\SHFileSystem.cpp" /> <ClCompile Include="src\Filesystem\SHFileSystem.cpp" />
<ClCompile Include="src\FRC\SHFramerateController.cpp" />
<ClCompile Include="src\Graphics\Buffers\SHVkBuffer.cpp" /> <ClCompile Include="src\Graphics\Buffers\SHVkBuffer.cpp" />
<ClCompile Include="src\Graphics\Commands\SHVkCommandBuffer.cpp" /> <ClCompile Include="src\Graphics\Commands\SHVkCommandBuffer.cpp" />
<ClCompile Include="src\Graphics\Commands\SHVkCommandPool.cpp" /> <ClCompile Include="src\Graphics\Commands\SHVkCommandPool.cpp" />

View File

@ -387,6 +387,7 @@
<ClInclude Include="src\Tools\SHUtilities.h"> <ClInclude Include="src\Tools\SHUtilities.h">
<Filter>Tools</Filter> <Filter>Tools</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\FRC\SHFramerateController.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\ECS_Base\Components\SHComponent.cpp"> <ClCompile Include="src\ECS_Base\Components\SHComponent.cpp">
@ -591,5 +592,6 @@
<ClCompile Include="src\Tools\SHLogger.cpp"> <ClCompile Include="src\Tools\SHLogger.cpp">
<Filter>Tools</Filter> <Filter>Tools</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\FRC\SHFramerateController.cpp" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -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 <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;
}
}
}

View File

@ -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