136 lines
4.2 KiB
C++
136 lines
4.2 KiB
C++
#include "GameEngine.h"
|
|
#include <sstream>
|
|
#include <iomanip>
|
|
|
|
GameEngine::ProfilerOverlay::ProfilerOverlay(sf::Font& fontRef)
|
|
: font(fontRef), visible(false), updateInterval(10), frameCounter(0)
|
|
{
|
|
text.setFont(font);
|
|
text.setCharacterSize(14);
|
|
text.setFillColor(sf::Color::White);
|
|
text.setPosition(10.0f, 10.0f);
|
|
|
|
// Semi-transparent dark background
|
|
background.setFillColor(sf::Color(0, 0, 0, 180));
|
|
background.setPosition(5.0f, 5.0f);
|
|
}
|
|
|
|
void GameEngine::ProfilerOverlay::toggle() {
|
|
visible = !visible;
|
|
}
|
|
|
|
void GameEngine::ProfilerOverlay::setVisible(bool vis) {
|
|
visible = vis;
|
|
}
|
|
|
|
bool GameEngine::ProfilerOverlay::isVisible() const {
|
|
return visible;
|
|
}
|
|
|
|
sf::Color GameEngine::ProfilerOverlay::getPerformanceColor(float frameTimeMs) {
|
|
if (frameTimeMs < 16.6f) {
|
|
return sf::Color::Green; // 60+ FPS
|
|
} else if (frameTimeMs < 33.3f) {
|
|
return sf::Color::Yellow; // 30-60 FPS
|
|
} else {
|
|
return sf::Color::Red; // <30 FPS
|
|
}
|
|
}
|
|
|
|
std::string GameEngine::ProfilerOverlay::formatFloat(float value, int precision) {
|
|
std::stringstream ss;
|
|
ss << std::fixed << std::setprecision(precision) << value;
|
|
return ss.str();
|
|
}
|
|
|
|
std::string GameEngine::ProfilerOverlay::formatPercentage(float part, float total) {
|
|
if (total <= 0.0f) return "0%";
|
|
float pct = (part / total) * 100.0f;
|
|
return formatFloat(pct, 0) + "%";
|
|
}
|
|
|
|
void GameEngine::ProfilerOverlay::update(const ProfilingMetrics& metrics) {
|
|
if (!visible) return;
|
|
|
|
// Only update text every N frames to reduce overhead
|
|
frameCounter++;
|
|
if (frameCounter < updateInterval) {
|
|
return;
|
|
}
|
|
frameCounter = 0;
|
|
|
|
std::stringstream ss;
|
|
ss << "McRogueFace Performance Monitor\n";
|
|
ss << "================================\n";
|
|
|
|
// Frame time and FPS
|
|
float frameMs = metrics.avgFrameTime;
|
|
ss << "FPS: " << metrics.fps << " (" << formatFloat(frameMs, 1) << "ms/frame)\n";
|
|
|
|
// Performance warning
|
|
if (frameMs > 33.3f) {
|
|
ss << "WARNING: Frame time exceeds 30 FPS target!\n";
|
|
}
|
|
|
|
ss << "\n";
|
|
|
|
// Timing breakdown
|
|
ss << "Frame Time Breakdown:\n";
|
|
ss << " Grid Render: " << formatFloat(metrics.gridRenderTime, 1) << "ms ("
|
|
<< formatPercentage(metrics.gridRenderTime, frameMs) << ")\n";
|
|
ss << " Cells: " << metrics.gridCellsRendered << " rendered\n";
|
|
ss << " Entities: " << metrics.entitiesRendered << " / " << metrics.totalEntities << " drawn\n";
|
|
|
|
if (metrics.fovOverlayTime > 0.01f) {
|
|
ss << " FOV Overlay: " << formatFloat(metrics.fovOverlayTime, 1) << "ms\n";
|
|
}
|
|
|
|
if (metrics.entityRenderTime > 0.01f) {
|
|
ss << " Entity Render: " << formatFloat(metrics.entityRenderTime, 1) << "ms ("
|
|
<< formatPercentage(metrics.entityRenderTime, frameMs) << ")\n";
|
|
}
|
|
|
|
if (metrics.pythonScriptTime > 0.01f) {
|
|
ss << " Python: " << formatFloat(metrics.pythonScriptTime, 1) << "ms ("
|
|
<< formatPercentage(metrics.pythonScriptTime, frameMs) << ")\n";
|
|
}
|
|
|
|
if (metrics.animationTime > 0.01f) {
|
|
ss << " Animations: " << formatFloat(metrics.animationTime, 1) << "ms ("
|
|
<< formatPercentage(metrics.animationTime, frameMs) << ")\n";
|
|
}
|
|
|
|
ss << "\n";
|
|
|
|
// Other metrics
|
|
ss << "Draw Calls: " << metrics.drawCalls << "\n";
|
|
ss << "UI Elements: " << metrics.uiElements << " (" << metrics.visibleElements << " visible)\n";
|
|
|
|
// Calculate unaccounted time
|
|
float accountedTime = metrics.gridRenderTime + metrics.entityRenderTime +
|
|
metrics.pythonScriptTime + metrics.animationTime;
|
|
float unaccountedTime = frameMs - accountedTime;
|
|
|
|
if (unaccountedTime > 1.0f) {
|
|
ss << "\n";
|
|
ss << "Other: " << formatFloat(unaccountedTime, 1) << "ms ("
|
|
<< formatPercentage(unaccountedTime, frameMs) << ")\n";
|
|
}
|
|
|
|
ss << "\n";
|
|
ss << "Press F3 to hide this overlay";
|
|
|
|
text.setString(ss.str());
|
|
|
|
// Update background size to fit text
|
|
sf::FloatRect textBounds = text.getLocalBounds();
|
|
background.setSize(sf::Vector2f(textBounds.width + 20.0f, textBounds.height + 20.0f));
|
|
}
|
|
|
|
void GameEngine::ProfilerOverlay::render(sf::RenderTarget& target) {
|
|
if (!visible) return;
|
|
|
|
target.draw(background);
|
|
target.draw(text);
|
|
}
|