#include "Game.hpp" #include "icon.h" #include #include #include #include #include "Engine/Utils/Perfs.hpp" #include "Engine/Utils/Timers.hpp" using std::make_shared; using std::make_unique; #define TARGET_FPS (60) std::unique_ptr mPerfsTimer = nullptr; Game::Game(bool dbg) : mbDbgModeEnabled(dbg) { InitWindows(); mCockpitUI = make_unique(); mWorldUI = make_unique(); if (mbDbgModeEnabled) { mDbgUI = make_unique(); mPerfsTimer = make_unique(); mPerfsTimer->Reset(); } } void Game::InitWindows() { // Create default game window sf::ContextSettings sWindowSettings; sWindowSettings.depthBits = 0; sWindowSettings.stencilBits = 0; sWindowSettings.antialiasingLevel = 8; sWindowSettings.sRgbCapable = true; mMainWindow = make_shared( 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 msTicksMonitoring; static double mPrevdelta = 0; static unsigned int mFrameCnt = 0; double mDelta = time.GetDeltaTimeUs(); // Debug performance computations if (mDbgUI != nullptr && mPerfsTimer != nullptr) { msTicksMonitoring.push_back((mDelta - mPrevdelta) / (1000000/TARGET_FPS)); if (mPerfsTimer->GetDeltaTime() >= 1000) { // Re-evaluate CPU usage every seconds (for FP'S') double cpuUsage = 100 * std::accumulate(msTicksMonitoring.begin(), msTicksMonitoring.end(), (double)(0)) / msTicksMonitoring.size(); mDbgUI->UpdateDebugData(cpuUsage, ((mDelta - mPrevdelta) / 1000), mFrameCnt, (PerfsGetVirtMem() / 1000), (PerfsGetPhysMem() / 1000)); mFrameCnt = 0; msTicksMonitoring.clear(); mPerfsTimer->Reset(); } } sf::Event event; while (mMainWindow->pollEvent(event)) { if (event.type == sf::Event::Closed) mMainWindow->close(); } // Update game stats and internal stuff Update(); // Ugly way to wait for next frame... Maybe create a separate thread for rendering? //while(time.GetDeltaTime() < (1000/TARGET_FPS)) {} // Process to the final rendering if (time.GetDeltaTime() >= (1000/TARGET_FPS)) { Render(); mFrameCnt++; time.Reset(); mPrevdelta = -mDelta; } else { mPrevdelta = mDelta; } // Return the current process stat to the head process (TODO: convert to thread) if (mMainWindow->isOpen()) return GAME_RUNNING; else return GAME_QUIT; } void Game::Update() { mWorldUI->Update(); mCockpitUI->Update(); } void Game::Render() { // Clear the draw buffer mMainWindow->clear(sf::Color::Black); // Draw the arena view mWorldUI->Draw(mMainWindow); // Draw the UI above mCockpitUI->Draw(mMainWindow); // Draw the debug informations if enabled if (mDbgUI != nullptr) mDbgUI->DrawDebugData(mMainWindow); // Present the draw buffer mMainWindow->display(); }