fixed assertion
This commit is contained in:
43
src/main.cpp
43
src/main.cpp
@ -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();
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user