From 59dc3a1638357863b56688859cfafa3b25ab6889 Mon Sep 17 00:00:00 2001 From: Gregor Klevze Date: Sun, 7 Dec 2025 10:29:20 +0100 Subject: [PATCH] fixed statistics panel --- src/graphics/renderers/GameRenderer.cpp | 73 ++++++++++++++----------- src/main.cpp | 42 ++++++++++++-- 2 files changed, 78 insertions(+), 37 deletions(-) diff --git a/src/graphics/renderers/GameRenderer.cpp b/src/graphics/renderers/GameRenderer.cpp index 15ef2f8..f875fd5 100644 --- a/src/graphics/renderers/GameRenderer.cpp +++ b/src/graphics/renderers/GameRenderer.cpp @@ -237,10 +237,22 @@ void GameRenderer::renderPlayingState( 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 panel backgrounds - SDL_SetRenderDrawColor(renderer, 10, 15, 25, 160); - SDL_FRect lbg{statsX - 16, gridY - 10, statsW + 32, GRID_H + 20}; - SDL_RenderFillRect(renderer, &lbg); + // Draw stats panel backdrop using the same art as the score panel + const float blocksPanelPadLeft = 34.0f; + const float blocksPanelPadRight = 10.0f; + const float blocksPanelPadY = 26.0f; + SDL_FRect blocksPanelBg{ + statsX - blocksPanelPadLeft, + gridY - blocksPanelPadY, + statsW + blocksPanelPadLeft + blocksPanelPadRight, + GRID_H + blocksPanelPadY * 2.0f + }; + if (scorePanelTex) { + SDL_RenderTexture(renderer, scorePanelTex, nullptr, &blocksPanelBg); + } else { + SDL_SetRenderDrawColor(renderer, 12, 18, 32, 205); + SDL_RenderFillRect(renderer, &blocksPanelBg); + } // Draw grid lines SDL_SetRenderDrawColor(renderer, 40, 45, 60, 255); @@ -302,10 +314,6 @@ void GameRenderer::renderPlayingState( s_inGridStarfield.draw(renderer, gridX, gridY, 0.22f, true); SDL_SetRenderDrawBlendMode(renderer, oldBlend); - // Draw block statistics panel border - drawRectWithOffset(statsX - 3 - contentOffsetX, statsY - 3 - contentOffsetY, statsW + 6, statsH + 6, {100, 120, 200, 255}); - drawRectWithOffset(statsX - contentOffsetX, statsY - contentOffsetY, statsW, statsH, {30, 35, 50, 255}); - // Draw next piece preview panel border drawRectWithOffset(nextX - 3 - contentOffsetX, nextY - 3 - contentOffsetY, nextW + 6, nextH + 6, {100, 120, 200, 255}); drawRectWithOffset(nextX - contentOffsetX, nextY - contentOffsetY, nextW, nextH, {30, 35, 50, 255}); @@ -565,24 +573,23 @@ void GameRenderer::renderPlayingState( } // Draw block statistics (left panel) - pixelFont->draw(renderer, statsX + 10, statsY + 10, "BLOCKS", 1.0f, {255, 220, 0, 255}); - const auto& blockCounts = game->getBlockCounts(); int totalBlocks = 0; for (int i = 0; i < PIECE_COUNT; ++i) totalBlocks += blockCounts[i]; - const float rowPadding = 18.0f; + const float rowPadding = 34.0f; const float rowWidth = statsW - rowPadding * 2.0f; - const float rowSpacing = 12.0f; - float yCursor = statsY + 44.0f; + const float rowSpacing = 18.0f; + float yCursor = statsY + 34.0f; for (int i = 0; i < PIECE_COUNT; ++i) { float rowTop = yCursor; - float previewSize = finalBlockSize * 0.52f; - float previewX = statsX + rowPadding; - float previewY = rowTop - 14.0f; + float rowLeft = statsX + rowPadding; + float rowRight = rowLeft + rowWidth; + float previewSize = finalBlockSize * 0.5f; + float previewX = rowLeft; + float previewY = rowTop - 10.0f; - // Determine actual preview height to keep bars below the blocks Game::Piece previewPiece{}; previewPiece.type = static_cast(i); int maxCy = -1; @@ -600,36 +607,35 @@ void GameRenderer::renderPlayingState( snprintf(countStr, sizeof(countStr), "%d", count); int countW = 0, countH = 0; pixelFont->measure(countStr, 1.0f, countW, countH); - float countX = previewX + rowWidth - static_cast(countW); - float countY = previewY + 9.0f; + float countX = rowRight - static_cast(countW); + float countY = previewY + 4.0f; int perc = (totalBlocks > 0) ? int(std::round(100.0 * double(count) / double(totalBlocks))) : 0; char percStr[16]; snprintf(percStr, sizeof(percStr), "%d%%", perc); - float barX = previewX; - float barY = previewY + pieceHeight + 12.0f; - float barH = 6.0f; - float barW = rowWidth; - float percY = barY + barH + 8.0f; + float barX = rowLeft + previewSize + 36.0f; + float barY = previewY + pieceHeight + 10.0f; + float barH = 7.0f; + float barW = std::max(0.0f, rowRight - barX); + float percY = barY + barH + 6.0f; - float rowBottom = percY + 16.0f; + float rowBottom = percY + 18.0f; SDL_FRect rowBg{ - previewX - 12.0f, + rowLeft - 18.0f, rowTop - 14.0f, - rowWidth + 24.0f, + rowWidth + 36.0f, rowBottom - (rowTop - 14.0f) }; - SDL_SetRenderDrawColor(renderer, 18, 26, 40, 200); + SDL_SetRenderDrawColor(renderer, 6, 12, 26, 205); SDL_RenderFillRect(renderer, &rowBg); - SDL_SetRenderDrawColor(renderer, 70, 100, 150, 210); + SDL_SetRenderDrawColor(renderer, 30, 60, 110, 220); SDL_RenderRect(renderer, &rowBg); drawSmallPiece(renderer, blocksTex, static_cast(i), previewX, previewY, previewSize); pixelFont->draw(renderer, countX, countY, countStr, 1.0f, {245, 245, 255, 255}); - pixelFont->draw(renderer, previewX, percY, percStr, 0.8f, {215, 225, 240, 255}); - SDL_SetRenderDrawColor(renderer, 110, 120, 140, 200); + SDL_SetRenderDrawColor(renderer, 32, 44, 70, 210); SDL_FRect track{barX, barY, barW, barH}; SDL_RenderFillRect(renderer, &track); SDL_Color pc = COLORS[i + 1]; @@ -638,6 +644,11 @@ void GameRenderer::renderPlayingState( fillW = std::clamp(fillW, 0.0f, barW); SDL_FRect fill{barX, barY, fillW, barH}; SDL_RenderFillRect(renderer, &fill); + SDL_SetRenderDrawColor(renderer, 255, 255, 255, 45); + SDL_FRect fillHighlight{barX, barY, fillW, barH * 0.35f}; + SDL_RenderFillRect(renderer, &fillHighlight); + + pixelFont->draw(renderer, barX, percY, percStr, 0.78f, {185, 205, 230, 255}); yCursor = rowBottom + rowSpacing; } diff --git a/src/main.cpp b/src/main.cpp index bf8b64b..d8d571a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -247,6 +247,31 @@ static void renderScaledBackground(SDL_Renderer* renderer, SDL_Texture* tex, int SDL_SetTextureAlphaMod(tex, 255); } +static void renderDynamicBackground(SDL_Renderer* renderer, SDL_Texture* tex, int winW, int winH, float baseScale, float motionClockMs, float alphaMul = 1.0f) { + if (!renderer || !tex) { + return; + } + + const float seconds = motionClockMs * 0.001f; + const float wobble = std::max(0.4f, baseScale + std::sin(seconds * 0.07f) * 0.02f + std::sin(seconds * 0.23f) * 0.01f); + const float rotation = std::sin(seconds * 0.035f) * 1.25f; + const float panX = std::sin(seconds * 0.11f) * winW * 0.02f; + const float panY = std::cos(seconds * 0.09f) * winH * 0.015f; + + SDL_FRect dest{ + (winW - winW * wobble) * 0.5f + panX, + (winH - winH * wobble) * 0.5f + panY, + winW * wobble, + winH * wobble + }; + SDL_FPoint center{dest.w * 0.5f, dest.h * 0.5f}; + + Uint8 alpha = static_cast(std::clamp(alphaMul, 0.0f, 1.0f) * 255.0f); + SDL_SetTextureAlphaMod(tex, alpha); + SDL_RenderTextureRotated(renderer, tex, nullptr, &dest, rotation, ¢er, SDL_FLIP_NONE); + SDL_SetTextureAlphaMod(tex, 255); +} + static void drawOverlay(SDL_Renderer* renderer, const SDL_FRect& rect, SDL_Color color, Uint8 alpha) { if (!renderer || alpha == 0) { return; @@ -257,7 +282,7 @@ static void drawOverlay(SDL_Renderer* renderer, const SDL_FRect& rect, SDL_Color SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE); } -static void renderLevelBackgrounds(const LevelBackgroundFader& fader, SDL_Renderer* renderer, int winW, int winH) { +static void renderLevelBackgrounds(const LevelBackgroundFader& fader, SDL_Renderer* renderer, int winW, int winH, float motionClockMs) { if (!renderer) { return; } @@ -265,12 +290,13 @@ static void renderLevelBackgrounds(const LevelBackgroundFader& fader, SDL_Render SDL_FRect fullRect{0.f, 0.f, static_cast(winW), static_cast(winH)}; const float duration = std::max(1.0f, fader.phaseDurationMs); const float progress = (fader.phase == LevelBackgroundPhase::Idle) ? 0.0f : std::clamp(fader.phaseElapsedMs / duration, 0.0f, 1.0f); + const float seconds = motionClockMs * 0.001f; switch (fader.phase) { case LevelBackgroundPhase::ZoomOut: { const float scale = 1.0f + progress * 0.15f; if (fader.currentTex) { - renderScaledBackground(renderer, fader.currentTex, winW, winH, scale, Uint8((1.0f - progress * 0.4f) * 255.0f)); + renderDynamicBackground(renderer, fader.currentTex, winW, winH, scale, motionClockMs, (1.0f - progress * 0.4f)); drawOverlay(renderer, fullRect, SDL_Color{0, 0, 0, 255}, Uint8(progress * 200.0f)); } break; @@ -279,16 +305,18 @@ static void renderLevelBackgrounds(const LevelBackgroundFader& fader, SDL_Render const float scale = 1.10f - progress * 0.10f; const Uint8 alpha = Uint8((0.4f + progress * 0.6f) * 255.0f); if (fader.currentTex) { - renderScaledBackground(renderer, fader.currentTex, winW, winH, scale, alpha); + renderDynamicBackground(renderer, fader.currentTex, winW, winH, scale, motionClockMs, alpha / 255.0f); } break; } case LevelBackgroundPhase::Idle: default: if (fader.currentTex) { - renderScaledBackground(renderer, fader.currentTex, winW, winH, 1.0f, 255); + renderDynamicBackground(renderer, fader.currentTex, winW, winH, 1.02f, motionClockMs, 1.0f); + float pulse = 0.35f + 0.25f * (0.5f + 0.5f * std::sin(seconds * 0.5f)); + drawOverlay(renderer, fullRect, SDL_Color{5, 12, 28, 255}, Uint8(pulse * 90.0f)); } else if (fader.nextTex) { - renderScaledBackground(renderer, fader.nextTex, winW, winH, 1.0f, 255); + renderDynamicBackground(renderer, fader.nextTex, winW, winH, 1.02f, motionClockMs, 1.0f); } else { drawOverlay(renderer, fullRect, SDL_Color{0, 0, 0, 255}, 255); } @@ -803,6 +831,7 @@ int main(int, char **) int gameplayCountdownIndex = 0; const double GAMEPLAY_COUNTDOWN_STEP_MS = 400.0; const std::array GAMEPLAY_COUNTDOWN_LABELS = { "3", "2", "1", "START" }; + double gameplayBackgroundClockMs = 0.0; // Instantiate state manager StateManager stateMgr(state); @@ -1268,6 +1297,7 @@ int main(int, char **) // Cap frame time to avoid spiral of death (max 100ms) if (frameMs > 100.0) frameMs = 100.0; + gameplayBackgroundClockMs += frameMs; const bool *ks = SDL_GetKeyboardState(nullptr); bool left = state == AppState::Playing && ks[SDL_SCANCODE_LEFT]; bool right = state == AppState::Playing && ks[SDL_SCANCODE_RIGHT]; @@ -1573,7 +1603,7 @@ int main(int, char **) if (state == AppState::Playing) { int bgLevel = std::clamp(game.level(), 0, 32); queueLevelBackground(levelBackgrounds, renderer, bgLevel); - renderLevelBackgrounds(levelBackgrounds, renderer, winW, winH); + renderLevelBackgrounds(levelBackgrounds, renderer, winW, winH, static_cast(gameplayBackgroundClockMs)); } else if (state == AppState::Loading) { // Use 3D starfield for loading screen (full screen) starfield3D.draw(renderer);