Added hold block and minor fixes

This commit is contained in:
2025-12-20 11:10:23 +01:00
parent 38dbc17ace
commit a520de6c1f
20 changed files with 467 additions and 50 deletions

View File

@ -77,7 +77,11 @@ bool AssetLoader::performStep() {
m_errors.push_back(std::string("CreateTexture failed: ") + fullPath);
} else {
std::lock_guard<std::mutex> lk(m_texturesMutex);
m_textures[path] = tex;
auto& slot = m_textures[path];
if (slot && slot != tex) {
SDL_DestroyTexture(slot);
}
slot = tex;
}
}
@ -95,6 +99,19 @@ bool AssetLoader::performStep() {
}
}
void AssetLoader::adoptTexture(const std::string& path, SDL_Texture* texture) {
if (!texture) {
return;
}
std::lock_guard<std::mutex> lk(m_texturesMutex);
auto& slot = m_textures[path];
if (slot && slot != texture) {
SDL_DestroyTexture(slot);
}
slot = texture;
}
float AssetLoader::getProgress() const {
int total = m_totalTasks.load(std::memory_order_relaxed);
if (total <= 0) return 1.0f;

View File

@ -39,6 +39,10 @@ public:
// Get a loaded texture (or nullptr if not loaded).
SDL_Texture* getTexture(const std::string& path) const;
// Adopt an externally-created texture so AssetLoader owns its lifetime.
// If a texture is already registered for this path, it will be replaced.
void adoptTexture(const std::string& path, SDL_Texture* texture);
// Return currently-loading path (empty when idle).
std::string getCurrentLoading() const;

View File

@ -139,6 +139,7 @@ struct TetrisApp::Impl {
SDL_Texture* scorePanelTex = nullptr;
SDL_Texture* statisticsPanelTex = nullptr;
SDL_Texture* nextPanelTex = nullptr;
SDL_Texture* holdPanelTex = nullptr;
BackgroundManager levelBackgrounds;
int startLevelSelection = 0;
@ -973,7 +974,8 @@ void TetrisApp::Impl::runLoop()
"assets/images/blocks90px_001.bmp",
"assets/images/panel_score.png",
"assets/images/statistics_panel.png",
"assets/images/next_panel.png"
"assets/images/next_panel.png",
"assets/images/hold_panel.png"
};
for (auto &p : queuedPaths) {
loadingManager->queueTexture(p);
@ -1007,10 +1009,11 @@ void TetrisApp::Impl::runLoop()
logoTex = assetLoader.getTexture("assets/images/spacetris.png");
logoSmallTex = assetLoader.getTexture("assets/images/spacetris.png");
mainScreenTex = assetLoader.getTexture("assets/images/main_screen.png");
blocksTex = assetLoader.getTexture("assets/images/blocks90px_001.bmp");
blocksTex = assetLoader.getTexture("assets/images/blocks90px_001.png");
scorePanelTex = assetLoader.getTexture("assets/images/panel_score.png");
statisticsPanelTex = assetLoader.getTexture("assets/images/statistics_panel.png");
nextPanelTex = assetLoader.getTexture("assets/images/next_panel.png");
holdPanelTex = assetLoader.getTexture("assets/images/hold_panel.png");
auto ensureTextureSize = [&](SDL_Texture* tex, int& outW, int& outH) {
if (!tex) return;
@ -1027,17 +1030,22 @@ void TetrisApp::Impl::runLoop()
auto legacyLoad = [&](const std::string& p, SDL_Texture*& outTex, int* outW = nullptr, int* outH = nullptr) {
if (!outTex) {
outTex = textureLoader->loadFromImage(renderer, p, outW, outH);
SDL_Texture* loaded = textureLoader->loadFromImage(renderer, p, outW, outH);
if (loaded) {
outTex = loaded;
assetLoader.adoptTexture(p, loaded);
}
}
};
legacyLoad("assets/images/spacetris.png", logoTex);
legacyLoad("assets/images/spacetris.png", logoSmallTex, &logoSmallW, &logoSmallH);
legacyLoad("assets/images/main_screen.png", mainScreenTex, &mainScreenW, &mainScreenH);
legacyLoad("assets/images/blocks90px_001.bmp", blocksTex);
legacyLoad("assets/images/blocks90px_001.png", blocksTex);
legacyLoad("assets/images/panel_score.png", scorePanelTex);
legacyLoad("assets/images/statistics_panel.png", statisticsPanelTex);
legacyLoad("assets/images/next_panel.png", nextPanelTex);
legacyLoad("assets/images/hold_panel.png", holdPanelTex);
if (!blocksTex) {
blocksTex = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 630, 90);
@ -1051,6 +1059,9 @@ void TetrisApp::Impl::runLoop()
SDL_RenderFillRect(renderer, &rect);
}
SDL_SetRenderTarget(renderer, nullptr);
// Ensure the generated fallback texture is cleaned up with other assets.
assetLoader.adoptTexture("assets/images/blocks90px_001.png", blocksTex);
}
if (musicLoaded) {
@ -1192,6 +1203,7 @@ void TetrisApp::Impl::runLoop()
ctx.scorePanelTex = scorePanelTex;
ctx.statisticsPanelTex = statisticsPanelTex;
ctx.nextPanelTex = nextPanelTex;
ctx.holdPanelTex = holdPanelTex;
ctx.mainScreenTex = mainScreenTex;
ctx.mainScreenW = mainScreenW;
ctx.mainScreenH = mainScreenH;
@ -1417,7 +1429,14 @@ void TetrisApp::Impl::runLoop()
break;
case AppState::Menu:
if (!mainScreenTex) {
mainScreenTex = textureLoader->loadFromImage(renderer, "assets/images/main_screen.png", &mainScreenW, &mainScreenH);
mainScreenTex = assetLoader.getTexture("assets/images/main_screen.png");
}
if (!mainScreenTex) {
SDL_Texture* loaded = textureLoader->loadFromImage(renderer, "assets/images/main_screen.png", &mainScreenW, &mainScreenH);
if (loaded) {
assetLoader.adoptTexture("assets/images/main_screen.png", loaded);
mainScreenTex = loaded;
}
}
if (menuState) {
menuState->drawMainButtonNormally = false;
@ -1490,6 +1509,7 @@ void TetrisApp::Impl::runLoop()
ctx.statisticsPanelTex,
scorePanelTex,
nextPanelTex,
holdPanelTex,
(float)LOGICAL_W,
(float)LOGICAL_H,
logicalScale,
@ -1669,27 +1689,18 @@ void TetrisApp::Impl::shutdown()
{
Settings::instance().save();
if (logoTex) {
SDL_DestroyTexture(logoTex);
logoTex = nullptr;
}
if (mainScreenTex) {
SDL_DestroyTexture(mainScreenTex);
mainScreenTex = nullptr;
}
// BackgroundManager owns its own textures.
levelBackgrounds.reset();
if (blocksTex) {
SDL_DestroyTexture(blocksTex);
blocksTex = nullptr;
}
if (scorePanelTex) {
SDL_DestroyTexture(scorePanelTex);
scorePanelTex = nullptr;
}
if (logoSmallTex) {
SDL_DestroyTexture(logoSmallTex);
logoSmallTex = nullptr;
}
// All textures are owned by AssetLoader (including legacy fallbacks adopted above).
logoTex = nullptr;
logoSmallTex = nullptr;
backgroundTex = nullptr;
mainScreenTex = nullptr;
blocksTex = nullptr;
scorePanelTex = nullptr;
statisticsPanelTex = nullptr;
nextPanelTex = nullptr;
if (scoreLoader.joinable()) {
scoreLoader.join();
@ -1704,6 +1715,11 @@ void TetrisApp::Impl::shutdown()
lineEffect.shutdown();
Audio::instance().shutdown();
SoundEffectManager::instance().shutdown();
// Destroy textures before tearing down the renderer/window.
assetLoader.shutdown();
pixelFont.shutdown();
font.shutdown();
TTF_Quit();