fixed assertion

This commit is contained in:
2025-11-30 15:52:39 +01:00
parent 7f07036f07
commit b46246b74f
2 changed files with 36 additions and 11 deletions

View File

@ -16,6 +16,7 @@
#include <memory> #include <memory>
#include <filesystem> #include <filesystem>
#include <thread> #include <thread>
#include <atomic>
#include "audio/Audio.h" #include "audio/Audio.h"
#include "audio/SoundEffect.h" #include "audio/SoundEffect.h"
@ -696,7 +697,6 @@ int main(int, char **)
exeDir.string().c_str(), ec.message().c_str()); exeDir.string().c_str(), ec.message().c_str());
} }
#endif #endif
SDL_free(const_cast<char*>(basePathRaw));
} else { } else {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetBasePath() failed; asset lookups rely on current directory: %s", "SDL_GetBasePath() failed; asset lookups rely on current directory: %s",
@ -711,15 +711,13 @@ int main(int, char **)
pixelFont.init("assets/fonts/PressStart2P-Regular.ttf", 16); pixelFont.init("assets/fonts/PressStart2P-Regular.ttf", 16);
ScoreManager scores; ScoreManager scores;
std::atomic<bool> scoresLoadComplete{false};
// Load scores asynchronously but keep the worker alive until shutdown to avoid lifetime issues // Load scores asynchronously but keep the worker alive until shutdown to avoid lifetime issues
std::jthread scoreLoader([&scores]() { std::jthread scoreLoader([&scores, &scoresLoadComplete]() {
scores.load(); scores.load();
scoresLoadComplete.store(true, std::memory_order_release);
}); });
const auto ensureScoresLoaded = [&]() { std::jthread menuTrackLoader;
if (scoreLoader.joinable()) {
scoreLoader.join();
}
};
Starfield starfield; Starfield starfield;
starfield.init(200, LOGICAL_W, LOGICAL_H); starfield.init(200, LOGICAL_W, LOGICAL_H);
Starfield3D starfield3D; Starfield3D starfield3D;
@ -904,7 +902,7 @@ int main(int, char **)
// Allow states to access the state manager for transitions // Allow states to access the state manager for transitions
ctx.stateManager = &stateMgr; ctx.stateManager = &stateMgr;
ctx.game = &game; ctx.game = &game;
ctx.scores = &scores; ctx.scores = nullptr; // populated once async load finishes
ctx.starfield = &starfield; ctx.starfield = &starfield;
ctx.starfield3D = &starfield3D; ctx.starfield3D = &starfield3D;
ctx.font = &font; ctx.font = &font;
@ -938,6 +936,15 @@ int main(int, char **)
running = false; running = false;
}; };
auto ensureScoresLoaded = [&]() {
if (scoreLoader.joinable()) {
scoreLoader.join();
}
if (!ctx.scores) {
ctx.scores = &scores;
}
};
auto beginStateFade = [&](AppState targetState, bool armGameplayCountdown) { auto beginStateFade = [&](AppState targetState, bool armGameplayCountdown) {
if (!ctx.stateManager) { if (!ctx.stateManager) {
return; return;
@ -1023,6 +1030,10 @@ int main(int, char **)
// Playing, LevelSelect and GameOver currently use inline logic in main; we'll migrate later // Playing, LevelSelect and GameOver currently use inline logic in main; we'll migrate later
while (running) while (running)
{ {
if (!ctx.scores && scoresLoadComplete.load(std::memory_order_acquire)) {
ensureScoresLoaded();
}
int winW = 0, winH = 0; int winW = 0, winH = 0;
SDL_GetWindowSize(window, &winW, &winH); SDL_GetWindowSize(window, &winW, &winH);
@ -1460,14 +1471,17 @@ int main(int, char **)
// Load menu track once on first menu entry (in background to avoid blocking) // Load menu track once on first menu entry (in background to avoid blocking)
static bool menuTrackLoaded = false; static bool menuTrackLoaded = false;
if (!menuTrackLoaded) { if (!menuTrackLoaded) {
std::thread([]() { if (menuTrackLoader.joinable()) {
menuTrackLoader.join();
}
menuTrackLoader = std::jthread([]() {
std::string menuTrack = AssetPath::resolveWithExtensions("assets/music/Every Block You Take", { ".mp3" }); std::string menuTrack = AssetPath::resolveWithExtensions("assets/music/Every Block You Take", { ".mp3" });
if (!menuTrack.empty()) { if (!menuTrack.empty()) {
Audio::instance().setMenuTrack(menuTrack); Audio::instance().setMenuTrack(menuTrack);
} else { } else {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Menu track not found (Every Block You Take)"); SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Menu track not found (Every Block You Take)");
} }
}).detach(); });
menuTrackLoaded = true; menuTrackLoaded = true;
} }
@ -1959,6 +1973,15 @@ int main(int, char **)
// Save settings on exit // Save settings on exit
Settings::instance().save(); Settings::instance().save();
if (scoreLoader.joinable()) {
scoreLoader.join();
if (!ctx.scores) {
ctx.scores = &scores;
}
}
if (menuTrackLoader.joinable()) {
menuTrackLoader.join();
}
lineEffect.shutdown(); lineEffect.shutdown();
Audio::instance().shutdown(); Audio::instance().shutdown();
SoundEffectManager::instance().shutdown(); SoundEffectManager::instance().shutdown();

View File

@ -9,6 +9,7 @@
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <cmath> #include <cmath>
#include <vector>
// Use dynamic logical dimensions from GlobalState instead of hardcoded values // Use dynamic logical dimensions from GlobalState instead of hardcoded values
// This allows the UI to adapt when the window is resized or goes fullscreen // This allows the UI to adapt when the window is resized or goes fullscreen
@ -239,7 +240,8 @@ void MenuState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect logi
// High scores table with wave offset // High scores table with wave offset
float scoresStartY = topPlayersY + 70; // more spacing under title float scoresStartY = topPlayersY + 70; // more spacing under title
const auto &hs = ctx.scores ? ctx.scores->all() : *(new std::vector<ScoreEntry>()); static const std::vector<ScoreEntry> EMPTY_SCORES;
const auto& hs = ctx.scores ? ctx.scores->all() : EMPTY_SCORES;
size_t maxDisplay = std::min(hs.size(), size_t(12)); size_t maxDisplay = std::min(hs.size(), size_t(12));
// Draw table header // Draw table header