Main refactor and proper window management

This commit is contained in:
JackCarterSmith 2024-10-11 17:58:04 +02:00
parent 1496d03ead
commit 9ab9e476b9
Signed by: JackCarterSmith
GPG Key ID: 832E52F4E23F8F24
3 changed files with 60 additions and 43 deletions

View File

@ -1,14 +1,11 @@
#include "Game.hpp" #include "Game.hpp"
#include "icon.h"
#include <numeric> #include <numeric>
#include <SFML/System.hpp> #include <SFML/System.hpp>
#include <SFML/Window/ContextSettings.hpp>
#include <SFML/Window/Event.hpp> #include <SFML/Window/Event.hpp>
#include "Engine/Utils/Perfs.hpp" #include "Engine/Utils/Perfs.hpp"
#include "Engine/Utils/Timers.hpp"
using std::make_shared; using std::make_shared;
using std::make_unique; using std::make_unique;
@ -19,9 +16,7 @@ using std::make_unique;
std::unique_ptr<SysTimer> mPerfsTimer = nullptr; std::unique_ptr<SysTimer> mPerfsTimer = nullptr;
Game* Game::smInstance = nullptr; Game* Game::smInstance = nullptr;
Game::Game(bool dbgFlag) : mbDbgModeEnabled(dbgFlag) { Game::Game(std::shared_ptr<sf::RenderWindow> mainWnd, bool dbgFlag) : mbDbgModeEnabled(dbgFlag), mMainWindow(mainWnd) {
InitWindows();
mCockpitUI = make_unique<CockpitUI>(); mCockpitUI = make_unique<CockpitUI>();
mWorldUI = make_unique<WorldUI>(); mWorldUI = make_unique<WorldUI>();
@ -32,32 +27,12 @@ Game::Game(bool dbgFlag) : mbDbgModeEnabled(dbgFlag) {
} }
} }
void Game::InitWindows() { GAME_STATUS Game::Tick() {
// Create default game window
sf::ContextSettings sWindowSettings;
sWindowSettings.depthBits = 0;
sWindowSettings.stencilBits = 0;
sWindowSettings.antialiasingLevel = 8;
sWindowSettings.sRgbCapable = true;
mMainWindow = make_shared<sf::RenderWindow>(
sf::VideoMode(1280, 720), "ProtoTank",
(sf::Style::Close | sf::Style::Titlebar),
sWindowSettings
);
mMainWindow->setVerticalSyncEnabled(false); // Never use simultaneously with framerate limiter
mMainWindow->setFramerateLimit(60);
mMainWindow->setKeyRepeatEnabled(false);
mMainWindow->setMouseCursorVisible(true);
mMainWindow->setIcon(64, 64, _aicon_bin);
}
GAME_STATUS Game::Tick(SysTimer& time) {
static std::vector<double> msTicksMonitoring; static std::vector<double> msTicksMonitoring;
static double mPrevdelta = 0; static double mPrevdelta = 0;
static double mLastCycleSleepDelta = 0; static double mLastCycleSleepDelta = 0;
static unsigned int mFrameCnt = 0; static unsigned int mFrameCnt = 0;
double mDelta = time.GetDeltaTimeUs(); double mDelta = mSysTimer.GetDeltaTimeUs();
// Debug performance computations // Debug performance computations
if (mDbgUI != nullptr && mPerfsTimer != nullptr) { if (mDbgUI != nullptr && mPerfsTimer != nullptr) {
@ -66,7 +41,7 @@ GAME_STATUS Game::Tick(SysTimer& time) {
// This average CPU/cycle_time method can monitor when CPU is in overload state (>0%) or in underload one (<0%) // This average CPU/cycle_time method can monitor when CPU is in overload state (>0%) or in underload one (<0%)
double cpuUsage = 200 * std::accumulate(msTicksMonitoring.begin(), msTicksMonitoring.end(), (double)(0)) / msTicksMonitoring.size() - 100; double cpuUsage = 200 * std::accumulate(msTicksMonitoring.begin(), msTicksMonitoring.end(), (double)(0)) / msTicksMonitoring.size() - 100;
mDbgUI->UpdateDebugData(cpuUsage, (((1000000.f / TARGET_FPS) - mLastCycleSleepDelta) / 1000), ((-mPrevdelta + time.GetDeltaTimeUs()) / 1000), mFrameCnt, (PerfsGetVirtMem() / 1000), (PerfsGetPhysMem() / 1000)); mDbgUI->UpdateDebugData(cpuUsage, (((1000000.f / TARGET_FPS) - mLastCycleSleepDelta) / 1000), ((-mPrevdelta + mSysTimer.GetDeltaTimeUs()) / 1000), mFrameCnt, (PerfsGetVirtMem() / 1000), (PerfsGetPhysMem() / 1000));
mFrameCnt = 0; mFrameCnt = 0;
msTicksMonitoring.clear(); msTicksMonitoring.clear();
@ -87,16 +62,16 @@ GAME_STATUS Game::Tick(SysTimer& time) {
//while(time.GetDeltaTime() < (1000/TARGET_FPS)) {} //while(time.GetDeltaTime() < (1000/TARGET_FPS)) {}
// Process to the final rendering // Process to the final rendering
if (time.GetDeltaTime() >= (1000/TARGET_FPS)) { if (mSysTimer.GetDeltaTime() >= (1000/TARGET_FPS)) {
Render(); Render();
mFrameCnt++; mFrameCnt++;
time.Reset(); mSysTimer.Reset();
mDelta = -mDelta; mDelta = -mDelta;
} }
mPrevdelta = mDelta; mPrevdelta = mDelta;
// Sleep for remaining time to avoid useless CPU usage // Sleep for remaining time to avoid useless CPU usage
mLastCycleSleepDelta = (1000000.f / TARGET_FPS) - (-mPrevdelta + time.GetDeltaTimeUs()); mLastCycleSleepDelta = (1000000.f / TARGET_FPS) - (-mPrevdelta + mSysTimer.GetDeltaTimeUs());
if (mLastCycleSleepDelta > 0) if (mLastCycleSleepDelta > 0)
sf::sleep(sf::microseconds(mLastCycleSleepDelta)); sf::sleep(sf::microseconds(mLastCycleSleepDelta));
else else

View File

@ -15,9 +15,9 @@ typedef enum eGameStatus {
class Game final { class Game final {
public: public:
static Game& getInstance(bool dbgFlag) { static Game& getInstance(std::shared_ptr<sf::RenderWindow> mainWnd, bool dbgFlag) {
if (smInstance == nullptr) if (smInstance == nullptr)
smInstance = new Game(dbgFlag); smInstance = new Game(mainWnd, dbgFlag);
return *smInstance; return *smInstance;
} }
@ -28,20 +28,21 @@ public:
Game(Game const&) = delete; Game(Game const&) = delete;
Game& operator= (Game const&) = delete; Game& operator= (Game const&) = delete;
GAME_STATUS Tick(SysTimer& time); GAME_STATUS Tick();
private: private:
Game(bool dbgFlag) noexcept(false); Game(std::shared_ptr<sf::RenderWindow> mainWnd, bool dbgFlag) noexcept(false);
static Game* smInstance; static Game* smInstance;
void InitWindows();
void Update(); void Update();
void Render(); void Render();
bool mbDbgModeEnabled; bool mbDbgModeEnabled;
std::unique_ptr<DebugUI> mDbgUI = nullptr; std::unique_ptr<DebugUI> mDbgUI = nullptr;
std::shared_ptr<sf::RenderWindow> mMainWindow = nullptr; SysTimer mSysTimer;
std::shared_ptr<sf::RenderWindow> mMainWindow;
std::unique_ptr<CockpitUI> mCockpitUI = nullptr; std::unique_ptr<CockpitUI> mCockpitUI = nullptr;
std::unique_ptr<WorldUI> mWorldUI = nullptr; std::unique_ptr<WorldUI> mWorldUI = nullptr;

View File

@ -1,18 +1,33 @@
#include <stdexcept>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Window/ContextSettings.hpp>
#include "icon.h"
#include "Engine/Misc/Logger.hpp" #include "Engine/Misc/Logger.hpp"
#include "Game.hpp" #include "Game.hpp"
static std::shared_ptr<sf::RenderWindow> InitWindow();
int main(int argc, char** argv) { int main(int argc, char** argv) {
SysTimer mSysTimer;
Logger& log = Logger::getInstance(); Logger& log = Logger::getInstance();
log.PrintInfo(LOGGER_MSG_FT("Create main window"));
std::shared_ptr<sf::RenderWindow> mainWindow = nullptr;
try {
mainWindow = InitWindow();
} catch (const std::exception& ex) {
log.PrintCritical(std::string(ex.what()));
return EXIT_FAILURE;
}
log.PrintInfo(LOGGER_MSG_FT("Create game instance"));
Game& arcadeGame = Game::getInstance(mainWindow, true);
GAME_STATUS status = GAME_INIT; GAME_STATUS status = GAME_INIT;
log.PrintInfo(LOGGER_MSG_FT("Init game instance"));
Game& arcadeGame = Game::getInstance(true);
for ( ;; ) { for ( ;; ) {
status = arcadeGame.Tick(mSysTimer); status = arcadeGame.Tick();
if (status == GAME_QUIT) if (status == GAME_QUIT)
break; break;
@ -21,3 +36,29 @@ int main(int argc, char** argv) {
log.PrintInfo(LOGGER_MSG_FT("Bye bye!")); log.PrintInfo(LOGGER_MSG_FT("Bye bye!"));
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
static std::shared_ptr<sf::RenderWindow> InitWindow() {
// Create default game window
sf::ContextSettings sWindowSettings;
sWindowSettings.depthBits = 0;
sWindowSettings.stencilBits = 0;
sWindowSettings.antialiasingLevel = 8;
sWindowSettings.sRgbCapable = true;
auto wnd = std::make_shared<sf::RenderWindow>(
sf::VideoMode(1280, 720), "ProtoTank",
(sf::Style::Close | sf::Style::Titlebar),
sWindowSettings
);
if (wnd == nullptr)
throw std::runtime_error("Failed to create the window");
wnd->setVerticalSyncEnabled(false); // Never use simultaneously with framerate limiter
wnd->setFramerateLimit(60); // Never use simultaneously with VSync
wnd->setKeyRepeatEnabled(false);
wnd->setMouseCursorVisible(true);
wnd->setIcon(64, 64, _aicon_bin);
return wnd;
}