132 lines
4.0 KiB
C++
132 lines
4.0 KiB
C++
#include "Game.hpp"
|
|
#include "icon.h"
|
|
|
|
#include <iostream>
|
|
#include <numeric>
|
|
|
|
#include <SFML/System.hpp>
|
|
#include <SFML/Window/ContextSettings.hpp>
|
|
#include <SFML/Window/Event.hpp>
|
|
|
|
#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<SysTimer> mPerfsTimer = nullptr;
|
|
Game* Game::smInstance = nullptr;
|
|
|
|
Game::Game(bool dbgFlag) : mbDbgModeEnabled(dbgFlag) {
|
|
InitWindows();
|
|
|
|
mCockpitUI = make_unique<CockpitUI>();
|
|
mWorldUI = make_unique<WorldUI>();
|
|
|
|
if (mbDbgModeEnabled) {
|
|
mDbgUI = make_unique<DebugUI>();
|
|
mPerfsTimer = make_unique<SysTimer>();
|
|
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::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 double mPrevdelta = 0;
|
|
static double mLastCycleSleepDelta = 0;
|
|
static unsigned int mFrameCnt = 0;
|
|
double mDelta = time.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(), (double)(0)) / msTicksMonitoring.size() - 100;
|
|
|
|
mDbgUI->UpdateDebugData(cpuUsage, (((1000000.f / TARGET_FPS) - mLastCycleSleepDelta) / 1000), ((-mPrevdelta + time.GetDeltaTimeUs()) / 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();
|
|
mDelta = -mDelta;
|
|
}
|
|
mPrevdelta = mDelta;
|
|
|
|
// Sleep for remaining time to avoid useless CPU usage
|
|
mLastCycleSleepDelta = (1000000.f / TARGET_FPS) - (-mPrevdelta + time.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::Update() {
|
|
// Game logic calls should go here...
|
|
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();
|
|
} |