feat: console on new thread

This commit is contained in:
Pc
2026-01-26 22:46:33 +01:00
parent ffa5a929df
commit 233d4189d1
3 changed files with 33 additions and 25 deletions

View File

@@ -1,29 +1,40 @@
#include <iostream> #pragma once // Zabezpieczenie przed wielokrotnym dołączeniem
#include <chrono> #include <chrono>
class FPSCounter { class FPSCounter {
public: public:
FPSCounter() : frameCount(0), lastTime(std::chrono::high_resolution_clock::now()) {} FPSCounter() :
frameCount(0),
currentFPS(0.0),
currentFrameTime(0.0),
lastTime(std::chrono::high_resolution_clock::now()) {
}
void update() { // Zwraca true, jeśli minęła sekunda i zaktualizowano dane
bool update() {
frameCount++; frameCount++;
auto currentTime = std::chrono::high_resolution_clock::now(); auto currentTime = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = currentTime - lastTime; std::chrono::duration<double> elapsed = currentTime - lastTime;
// Aktualizujemy i wypisujemy TYLKO jeśli minęła co najmniej 1 sekunda
if (elapsed.count() >= 1.0) { if (elapsed.count() >= 1.0) {
double fps = frameCount / elapsed.count(); currentFPS = frameCount / elapsed.count();
double msPerFrame = 1000.0 / fps; // Obliczamy czas klatki w ms
currentFrameTime = 1000.0 / (currentFPS == 0 ? 1 : currentFPS);
std::cout << "FPS: " << (int)fps
<< " | Czas klatki: " << msPerFrame << " ms" << std::endl;
frameCount = 0; frameCount = 0;
lastTime = currentTime; lastTime = currentTime;
return true; // Zgłaszamy, że dane się zmieniły
} }
return false;
} }
// --- TEGO BRAKOWAŁO W TWOIM KODZIE ---
double getFPS() const { return currentFPS; }
double getFrameTime() const { return currentFrameTime; }
private: private:
int frameCount; long long frameCount;
double currentFPS; // Przechowuje ostatnio obliczone FPS
double currentFrameTime; // Przechowuje czas klatki
std::chrono::time_point<std::chrono::high_resolution_clock> lastTime; std::chrono::time_point<std::chrono::high_resolution_clock> lastTime;
}; };

View File

@@ -6,29 +6,27 @@
#include <condition_variable> #include <condition_variable>
#include <queue> #include <queue>
#include <atomic> #include <atomic>
#include <sstream> // <--- TO JEST NIEZBĘDNE
class AsyncLogger { class AsyncLogger {
public: public:
// Singleton - jedna instancja loggera na całą grę
static AsyncLogger& getInstance() { static AsyncLogger& getInstance() {
static AsyncLogger instance; static AsyncLogger instance;
return instance; return instance;
} }
// Dodaj wiadomość do kolejki (wywoływane z gry) - to jest super szybkie
void log(const std::string& message) { void log(const std::string& message) {
std::lock_guard<std::mutex> lock(queueMutex); std::lock_guard<std::mutex> lock(queueMutex);
logQueue.push(message); logQueue.push(message);
cv.notify_one(); // Obudź wątek loggera cv.notify_one();
} }
// Uruchom wątek (wywołaj raz na początku programu)
void start() { void start() {
if (running) return;
running = true; running = true;
loggingThread = std::thread(&AsyncLogger::processQueue, this); loggingThread = std::thread(&AsyncLogger::processQueue, this);
} }
// Zatrzymaj wątek (wywołaj przy zamykaniu)
void stop() { void stop() {
running = false; running = false;
cv.notify_one(); cv.notify_one();
@@ -41,20 +39,14 @@ private:
AsyncLogger() : running(false) {} AsyncLogger() : running(false) {}
~AsyncLogger() { stop(); } ~AsyncLogger() { stop(); }
// To jest funkcja, która działa w osobnym wątku
void processQueue() { void processQueue() {
while (running || !logQueue.empty()) { while (running || !logQueue.empty()) {
std::unique_lock<std::mutex> lock(queueMutex); std::unique_lock<std::mutex> lock(queueMutex);
// Czekaj, aż coś pojawi się w kolejce lub zakończymy program
cv.wait(lock, [this] { return !logQueue.empty() || !running; }); cv.wait(lock, [this] { return !logQueue.empty() || !running; });
while (!logQueue.empty()) { while (!logQueue.empty()) {
std::string msg = logQueue.front(); std::string msg = logQueue.front();
logQueue.pop(); logQueue.pop();
// Zwalniamy mutex przed wypisywaniem, żeby nie blokować głównego wątku
// gdy konsola jest "zamrożona" przez użytkownika
lock.unlock(); lock.unlock();
std::cout << msg << std::endl; std::cout << msg << std::endl;
@@ -71,5 +63,10 @@ private:
std::atomic<bool> running; std::atomic<bool> running;
}; };
// Makro dla wygody używania // --- POPRAWIONE MAKRO ---
#define LOG(msg) AsyncLogger::getInstance().log(msg) // Tworzy tymczasowy strumień (ostringstream), który "rozumie" operator <<
#define LOG(stream_args) { \
std::ostringstream ss; \
ss << stream_args; \
AsyncLogger::getInstance().log(ss.str()); \
}

View File

@@ -813,7 +813,7 @@ int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
// --- POPRAWKA 2: Używaj zapisanego hDC, a nie pobieraj nowego --- // --- POPRAWKA 2: Używaj zapisanego hDC, a nie pobieraj nowego ---
SwapBuffers(hDC); SwapBuffers(hDC);
LOG("FPS: " << fpsCounter.getFPS() << " | Czas: " << fpsCounter.getFrameTime() << "ms");
LimitFPS(targetFPS); LimitFPS(targetFPS);
} }
} }