ProtoTank/Game.cpp

121 lines
3.4 KiB
C++

#include "Game.hpp"
#include "icon.h"
#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(bool dbg) : mbDbgModeEnabled(dbg) {
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 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();
}