diff --git a/assets/images/background.png b/assets/images/old/background.png similarity index 100% rename from assets/images/background.png rename to assets/images/old/background.png diff --git a/assets/images/background.webp b/assets/images/old/background.webp similarity index 100% rename from assets/images/background.webp rename to assets/images/old/background.webp diff --git a/assets/images/main_background.webp b/assets/images/old/main_background.webp similarity index 100% rename from assets/images/main_background.webp rename to assets/images/old/main_background.webp diff --git a/assets/images/tetris_main_back_level0.jpg b/assets/images/old/tetris_main_back_level0.jpg similarity index 100% rename from assets/images/tetris_main_back_level0.jpg rename to assets/images/old/tetris_main_back_level0.jpg diff --git a/assets/images/tetris_main_level_0.webp b/assets/images/old/tetris_main_level_0.webp similarity index 100% rename from assets/images/tetris_main_level_0.webp rename to assets/images/old/tetris_main_level_0.webp diff --git a/assets/images/panel_score.png b/assets/images/panel_score.png new file mode 100644 index 0000000..5042621 Binary files /dev/null and b/assets/images/panel_score.png differ diff --git a/settings.ini b/settings.ini index 200523e..384ce2a 100644 --- a/settings.ini +++ b/settings.ini @@ -12,7 +12,7 @@ Sound=1 SmoothScroll=1 [Player] -Name=GREGOR +Name=PLAYER [Debug] Enabled=1 diff --git a/src/core/application/ApplicationManager.cpp b/src/core/application/ApplicationManager.cpp index d6e26d6..2f58484 100644 --- a/src/core/application/ApplicationManager.cpp +++ b/src/core/application/ApplicationManager.cpp @@ -1131,6 +1131,7 @@ void ApplicationManager::setupStateHandlers() { m_stateContext.pixelFont, m_stateContext.lineEffect, m_stateContext.blocksTex, + m_stateContext.scorePanelTex, LOGICAL_W, LOGICAL_H, logicalScale, diff --git a/src/graphics/GameRenderer.cpp b/src/graphics/GameRenderer.cpp index 8cb7552..63198a9 100644 --- a/src/graphics/GameRenderer.cpp +++ b/src/graphics/GameRenderer.cpp @@ -198,10 +198,19 @@ void GameRenderer::renderPlayingState( lineEffect->startLineClear(completedLines, static_cast(gridX), static_cast(gridY), static_cast(finalBlockSize)); } - // Draw game grid border - drawRectWithOffset(gridX - 3 - contentOffsetX, gridY - 3 - contentOffsetY, GRID_W + 6, GRID_H + 6, {100, 120, 200, 255}); - drawRectWithOffset(gridX - 1 - contentOffsetX, gridY - 1 - contentOffsetY, GRID_W + 2, GRID_H + 2, {60, 80, 160, 255}); - drawRectWithOffset(gridX - contentOffsetX, gridY - contentOffsetY, GRID_W, GRID_H, {20, 25, 35, 255}); + // Draw styled game grid border and semi-transparent background so the scene shows through. + SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); + + // Outer glow layers (subtle, increasing spread, decreasing alpha) + drawRectWithOffset(gridX - 8 - contentOffsetX, gridY - 8 - contentOffsetY, GRID_W + 16, GRID_H + 16, {100, 120, 200, 28}); + drawRectWithOffset(gridX - 6 - contentOffsetX, gridY - 6 - contentOffsetY, GRID_W + 12, GRID_H + 12, {100, 120, 200, 40}); + + // Accent border (brighter, thin) + drawRectWithOffset(gridX - 3 - contentOffsetX, gridY - 3 - contentOffsetY, GRID_W + 6, GRID_H + 6, {100, 120, 200, 220}); + drawRectWithOffset(gridX - 1 - contentOffsetX, gridY - 1 - contentOffsetY, GRID_W + 2, GRID_H + 2, {60, 80, 160, 200}); + + // Do NOT fill the interior of the grid so the background shows through. + // (Intentionally leave the playfield interior transparent.) // Draw panel backgrounds SDL_SetRenderDrawColor(renderer, 10, 15, 25, 160); @@ -211,7 +220,7 @@ void GameRenderer::renderPlayingState( SDL_FRect rbg{scoreX - 16, gridY - 16, statsW + 32, GRID_H + 32}; SDL_RenderFillRect(renderer, &rbg); - // Draw grid lines + // Draw grid lines (solid so grid remains legible over background) SDL_SetRenderDrawColor(renderer, 40, 45, 60, 255); for (int x = 1; x < Game::COLS; ++x) { float lineX = gridX + x * finalBlockSize; diff --git a/src/graphics/renderers/GameRenderer.cpp b/src/graphics/renderers/GameRenderer.cpp index 8ef3cb1..7080e94 100644 --- a/src/graphics/renderers/GameRenderer.cpp +++ b/src/graphics/renderers/GameRenderer.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include "../../core/Settings.h" @@ -147,6 +148,7 @@ void GameRenderer::renderPlayingState( FontAtlas* pixelFont, LineEffect* lineEffect, SDL_Texture* blocksTex, + SDL_Texture* scorePanelTex, float logicalW, float logicalH, float logicalScale, @@ -212,7 +214,6 @@ void GameRenderer::renderPlayingState( const float statsX = layoutStartX + contentOffsetX; const float gridX = layoutStartX + PANEL_WIDTH + PANEL_SPACING + contentOffsetX; - const float scoreX = layoutStartX + PANEL_WIDTH + PANEL_SPACING + GRID_W + PANEL_SPACING + contentOffsetX; const float gridY = contentStartY + NEXT_PIECE_HEIGHT + contentOffsetY; const float statsY = gridY; @@ -241,9 +242,6 @@ void GameRenderer::renderPlayingState( SDL_FRect lbg{statsX - 16, gridY - 10, statsW + 32, GRID_H + 20}; SDL_RenderFillRect(renderer, &lbg); - SDL_FRect rbg{scoreX - 16, gridY - 16, statsW + 32, GRID_H + 32}; - SDL_RenderFillRect(renderer, &rbg); - // Draw grid lines SDL_SetRenderDrawColor(renderer, 40, 45, 60, 255); for (int x = 1; x < Game::COLS; ++x) { @@ -650,22 +648,27 @@ void GameRenderer::renderPlayingState( const float contentPad = 36.0f; float scoreContentH = (contentBottomOffset - contentTopOffset) + contentPad; float baseY = gridY + (GRID_H - scoreContentH) * 0.5f; - - pixelFont->draw(renderer, scoreX, baseY + 0, "SCORE", 1.0f, {255, 220, 0, 255}); + + const float statsPanelGap = 12.0f; + const float statsPanelLeft = gridX + GRID_W + statsPanelGap; + const float statsPanelPadLeft = 40.0f; + const float statsPanelPadRight = 34.0f; + const float statsPanelPadY = 28.0f; + const float statsTextX = statsPanelLeft + statsPanelPadLeft; + + const SDL_Color labelColor{255, 220, 0, 255}; + const SDL_Color valueColor{255, 255, 255, 255}; + const SDL_Color nextColor{80, 255, 120, 255}; + char scoreStr[32]; snprintf(scoreStr, sizeof(scoreStr), "%d", game->score()); - pixelFont->draw(renderer, scoreX, baseY + 25, scoreStr, 0.9f, {255, 255, 255, 255}); - - pixelFont->draw(renderer, scoreX, baseY + 70, "LINES", 1.0f, {255, 220, 0, 255}); + char linesStr[16]; snprintf(linesStr, sizeof(linesStr), "%03d", game->lines()); - pixelFont->draw(renderer, scoreX, baseY + 95, linesStr, 0.9f, {255, 255, 255, 255}); - - pixelFont->draw(renderer, scoreX, baseY + 140, "LEVEL", 1.0f, {255, 220, 0, 255}); + char levelStr[16]; snprintf(levelStr, sizeof(levelStr), "%02d", game->level()); - pixelFont->draw(renderer, scoreX, baseY + 165, levelStr, 0.9f, {255, 255, 255, 255}); - + // Next level progress int startLv = game->startLevelBase(); int firstThreshold = (startLv + 1) * 10; @@ -678,46 +681,98 @@ void GameRenderer::renderPlayingState( nextThreshold = firstThreshold + ((blocksPast / 10) + 1) * 10; } int linesForNext = std::max(0, nextThreshold - linesDone); - pixelFont->draw(renderer, scoreX, baseY + 200, "NEXT LVL", 1.0f, {255, 220, 0, 255}); char nextStr[32]; snprintf(nextStr, sizeof(nextStr), "%d LINES", linesForNext); - pixelFont->draw(renderer, scoreX, baseY + 225, nextStr, 0.9f, {80, 255, 120, 255}); - + // Time display - pixelFont->draw(renderer, scoreX, baseY + 265, "TIME", 1.0f, {255, 220, 0, 255}); int totalSecs = static_cast(game->elapsed()); int mins = totalSecs / 60; int secs = totalSecs % 60; char timeStr[16]; snprintf(timeStr, sizeof(timeStr), "%02d:%02d", mins, secs); - pixelFont->draw(renderer, scoreX, baseY + 290, timeStr, 0.9f, {255, 255, 255, 255}); - - // Debug: Gravity timing info - if (Settings::instance().isDebugEnabled()) { - pixelFont->draw(renderer, scoreX, baseY + 330, "GRAVITY", 0.8f, {150, 150, 150, 255}); + + const bool debugEnabled = Settings::instance().isDebugEnabled(); + char gravityStr[32] = ""; + char dropStr[32] = ""; + char gravityHud[64] = ""; + SDL_Color dropColor{100, 255, 100, 255}; + if (debugEnabled) { double gravityMs = game->getGravityMs(); double fallAcc = game->getFallAccumulator(); - - // Calculate effective gravity (accounting for soft drop) bool isSoftDrop = game->isSoftDropping(); double effectiveGravityMs = isSoftDrop ? (gravityMs / 2.0) : gravityMs; double timeUntilDrop = std::max(0.0, effectiveGravityMs - fallAcc); - - char gravityStr[32]; + snprintf(gravityStr, sizeof(gravityStr), "%.0f ms%s", gravityMs, isSoftDrop ? " (SD)" : ""); - pixelFont->draw(renderer, scoreX, baseY + 350, gravityStr, 0.7f, {180, 180, 180, 255}); - - char dropStr[32]; snprintf(dropStr, sizeof(dropStr), "Drop: %.0f", timeUntilDrop); - SDL_Color dropColor = isSoftDrop ? SDL_Color{255, 200, 100, 255} : SDL_Color{100, 255, 100, 255}; - pixelFont->draw(renderer, scoreX, baseY + 370, dropStr, 0.7f, dropColor); - - // Gravity HUD (Top) - char gms[64]; - double gms_val = game->getGravityMs(); - double gfps = gms_val > 0.0 ? (1000.0 / gms_val) : 0.0; - snprintf(gms, sizeof(gms), "GRAV: %.0f ms (%.2f fps)", gms_val, gfps); - pixelFont->draw(renderer, logicalW - 260, 10, gms, 0.9f, {200, 200, 220, 255}); + dropColor = isSoftDrop ? SDL_Color{255, 200, 100, 255} : SDL_Color{100, 255, 100, 255}; + + double gfps = gravityMs > 0.0 ? (1000.0 / gravityMs) : 0.0; + snprintf(gravityHud, sizeof(gravityHud), "GRAV: %.0f ms (%.2f fps)", gravityMs, gfps); + } + + struct StatLine { + const char* text; + float offsetY; + float scale; + SDL_Color color; + }; + + std::vector statLines; + statLines.reserve(debugEnabled ? 13 : 10); + statLines.push_back({"SCORE", 0.0f, 1.0f, labelColor}); + statLines.push_back({scoreStr, 25.0f, 0.9f, valueColor}); + statLines.push_back({"LINES", 70.0f, 1.0f, labelColor}); + statLines.push_back({linesStr, 95.0f, 0.9f, valueColor}); + statLines.push_back({"LEVEL", 140.0f, 1.0f, labelColor}); + statLines.push_back({levelStr, 165.0f, 0.9f, valueColor}); + statLines.push_back({"NEXT LVL", 200.0f, 1.0f, labelColor}); + statLines.push_back({nextStr, 225.0f, 0.9f, nextColor}); + statLines.push_back({"TIME", 265.0f, 1.0f, labelColor}); + statLines.push_back({timeStr, 290.0f, 0.9f, valueColor}); + + if (debugEnabled) { + SDL_Color debugLabelColor{150, 150, 150, 255}; + SDL_Color debugValueColor{180, 180, 180, 255}; + statLines.push_back({"GRAVITY", 330.0f, 0.8f, debugLabelColor}); + statLines.push_back({gravityStr, 350.0f, 0.7f, debugValueColor}); + statLines.push_back({dropStr, 370.0f, 0.7f, dropColor}); + } + + if (!statLines.empty()) { + float statsContentTop = std::numeric_limits::max(); + float statsContentBottom = std::numeric_limits::lowest(); + float statsContentMaxWidth = 0.0f; + + for (const auto& line : statLines) { + int textW = 0; + int textH = 0; + pixelFont->measure(line.text, line.scale, textW, textH); + float y = baseY + line.offsetY; + statsContentTop = std::min(statsContentTop, y); + statsContentBottom = std::max(statsContentBottom, y + textH); + statsContentMaxWidth = std::max(statsContentMaxWidth, static_cast(textW)); + } + + float statsPanelWidth = statsPanelPadLeft + statsContentMaxWidth + statsPanelPadRight; + float statsPanelHeight = (statsContentBottom - statsContentTop) + statsPanelPadY * 2.0f; + float statsPanelTop = statsContentTop - statsPanelPadY; + + SDL_FRect statsBg{statsPanelLeft, statsPanelTop, statsPanelWidth, statsPanelHeight}; + if (scorePanelTex) { + SDL_RenderTexture(renderer, scorePanelTex, nullptr, &statsBg); + } else { + SDL_SetRenderDrawColor(renderer, 12, 18, 32, 205); + SDL_RenderFillRect(renderer, &statsBg); + } + } + + for (const auto& line : statLines) { + pixelFont->draw(renderer, statsTextX, baseY + line.offsetY, line.text, line.scale, line.color); + } + + if (debugEnabled) { + pixelFont->draw(renderer, logicalW - 260, 10, gravityHud, 0.9f, {200, 200, 220, 255}); } // Hold piece (if implemented) diff --git a/src/graphics/renderers/GameRenderer.h b/src/graphics/renderers/GameRenderer.h index 96422cf..ad3287b 100644 --- a/src/graphics/renderers/GameRenderer.h +++ b/src/graphics/renderers/GameRenderer.h @@ -21,6 +21,7 @@ public: FontAtlas* pixelFont, LineEffect* lineEffect, SDL_Texture* blocksTex, + SDL_Texture* scorePanelTex, float logicalW, float logicalH, float logicalScale, diff --git a/src/main.cpp b/src/main.cpp index da2b2a4..bf8b64b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -673,6 +673,11 @@ int main(int, char **) SDL_SetRenderTarget(renderer, nullptr); } + + SDL_Texture* scorePanelTex = loadTextureFromImage(renderer, "assets/images/panel_score.png"); + if (scorePanelTex) { + SDL_SetTextureBlendMode(scorePanelTex, SDL_BLENDMODE_BLEND); + } Game game(startLevelSelection); // Apply global gravity speed multiplier from config @@ -819,6 +824,7 @@ int main(int, char **) ctx.logoSmallH = logoSmallH; ctx.backgroundTex = backgroundTex; ctx.blocksTex = blocksTex; + ctx.scorePanelTex = scorePanelTex; ctx.mainScreenTex = mainScreenTex; ctx.mainScreenW = mainScreenW; ctx.mainScreenH = mainScreenH; @@ -1717,6 +1723,7 @@ int main(int, char **) &pixelFont, &lineEffect, blocksTex, + scorePanelTex, (float)LOGICAL_W, (float)LOGICAL_H, logicalScale, @@ -1956,6 +1963,8 @@ int main(int, char **) resetLevelBackgrounds(levelBackgrounds); if (blocksTex) SDL_DestroyTexture(blocksTex); + if (scorePanelTex) + SDL_DestroyTexture(scorePanelTex); if (logoSmallTex) SDL_DestroyTexture(logoSmallTex); diff --git a/src/states/PlayingState.cpp b/src/states/PlayingState.cpp index 01acecd..08db8fe 100644 --- a/src/states/PlayingState.cpp +++ b/src/states/PlayingState.cpp @@ -189,6 +189,7 @@ void PlayingState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect l ctx.pixelFont, ctx.lineEffect, ctx.blocksTex, + ctx.scorePanelTex, 1200.0f, // LOGICAL_W 1000.0f, // LOGICAL_H logicalScale, @@ -269,6 +270,7 @@ void PlayingState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect l ctx.pixelFont, ctx.lineEffect, ctx.blocksTex, + ctx.scorePanelTex, 1200.0f, 1000.0f, logicalScale, diff --git a/src/states/State.h b/src/states/State.h index 8981c05..7271044 100644 --- a/src/states/State.h +++ b/src/states/State.h @@ -40,6 +40,7 @@ struct StateContext { // backgroundTex is set once in `main.cpp` and passed to states via this context. // Prefer reading this field instead of relying on any `extern SDL_Texture*` globals. SDL_Texture* blocksTex = nullptr; + SDL_Texture* scorePanelTex = nullptr; SDL_Texture* mainScreenTex = nullptr; int mainScreenW = 0; int mainScreenH = 0;