#include "Game.hpp" #include #include #include #include #include "Engine/Misc/Logger.hpp" #include "Engine/Utils/Perfs.hpp" using std::make_shared; using std::make_unique; #define TARGET_FPS (60) Game* Game::smInstance = nullptr; Game::Game(std::shared_ptr mainWnd, bool dbgFlag) : mbDbgModeEnabled(dbgFlag), mMainWindow(mainWnd) { mWorld3D = make_shared(); mCockpitUI = make_unique(); mWorldUI = make_unique(mWorld3D); if (mbDbgModeEnabled) { mDbgUI = make_unique(); mPerfsTimer = make_unique(); mPerfsTimer->Reset(); } } GAME_STATUS Game::Tick() { static std::vector msTicksMonitoring; static double mPrevdelta = 0; static double mLastCycleSleepDelta = 0; static unsigned int mFrameCnt = 0; double mDelta = mSysTimer.GetDeltaTimeUs(); // Debug performance computations if (mDbgUI != nullptr && mPerfsTimer != nullptr) { msTicksMonitoring.push_back(((1000000.f / TARGET_FPS) - mLastCycleSleepDelta) * TARGET_FPS / 1000000.f); if (mPerfsTimer->GetDeltaTime() >= 1000) { // Every 1s // 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(), static_cast(0)) / msTicksMonitoring.size() - 100; mDbgUI->UpdateDebugData(cpuUsage, (((1000000.f / TARGET_FPS) - mLastCycleSleepDelta) / 1000), ((-mPrevdelta + mSysTimer.GetDeltaTimeUs()) / 1000), mFrameCnt, (PerfsGetVirtMem() / 1000), (PerfsGetPhysMem() / 1000)); mFrameCnt = 0; msTicksMonitoring.clear(); mPerfsTimer->Reset(); } } // 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 the window have the focus if (mSysTimer.GetDeltaTime() >= (1000/TARGET_FPS) && mMainWindow->hasFocus()) { Render(); mFrameCnt++; mSysTimer.Reset(); mDelta = -mDelta; } mPrevdelta = mDelta; // Sleep for remaining time to avoid useless CPU usage mLastCycleSleepDelta = (1000000.f / TARGET_FPS) - (-mPrevdelta + mSysTimer.GetDeltaTimeUs()); if (mLastCycleSleepDelta > 0) sf::sleep(sf::microseconds(mLastCycleSleepDelta)); else mLastCycleSleepDelta = 0; // 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::EventMouseMoved(int _x, int _y) { if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) { float dx = M3D_Deg2Rad(0.25f * static_cast(_x - mPrevMousePos.x)); float dy = M3D_Deg2Rad(0.25f * static_cast(_y - mPrevMousePos.y)); mWorld3D->UpdateCamera(CAMERA_MOVE_PITCH, dy); mWorld3D->UpdateCamera(CAMERA_MOVE_YAW, dx); } mPrevMousePos.x = _x; mPrevMousePos.y = _y; } void Game::Update() { // Refresh keyboard inputs KeyboardInputsCheck(); // Game logic calls should go here... mWorldUI->Update(); mCockpitUI->Update(); } void Game::KeyboardInputsCheck() { const float deltaTimeS = mSysTimer.GetDeltaTime() / 1000; if (mMainWindow->hasFocus()) { if (sf::Keyboard::isKeyPressed(sf::Keyboard::Z)) { if (sf::Keyboard::isKeyPressed(sf::Keyboard::Scan::LShift)) mWorld3D->UpdateCamera(CAMERA_MOVE_WALK, 15.0f * deltaTimeS); else mWorld3D->UpdateCamera(CAMERA_MOVE_WALK, 10.0f * deltaTimeS); } if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) { if (sf::Keyboard::isKeyPressed(sf::Keyboard::Scan::LShift)) mWorld3D->UpdateCamera(CAMERA_MOVE_WALK, -15.0f * deltaTimeS); else mWorld3D->UpdateCamera(CAMERA_MOVE_WALK, -10.0f * deltaTimeS); } if (sf::Keyboard::isKeyPressed(sf::Keyboard::Q)) mWorld3D->UpdateCamera(CAMERA_MOVE_STRAFE, -10.0f * deltaTimeS); if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) mWorld3D->UpdateCamera(CAMERA_MOVE_STRAFE, 10.0f * deltaTimeS); if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space)) mWorld3D->UpdateCamera(CAMERA_MOVE_FLY, 5.0f * deltaTimeS); if (sf::Keyboard::isKeyPressed(sf::Keyboard::LControl)) mWorld3D->UpdateCamera(CAMERA_MOVE_FLY, -5.0f * deltaTimeS); } } 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(); }