diff --git a/assets/images/statistics_panel.png b/assets/images/statistics_panel.png index 116c3de..19a59c1 100644 Binary files a/assets/images/statistics_panel.png and b/assets/images/statistics_panel.png differ diff --git a/src/graphics/renderers/GameRenderer.cpp b/src/graphics/renderers/GameRenderer.cpp index ed126aa..5c15cd4 100644 --- a/src/graphics/renderers/GameRenderer.cpp +++ b/src/graphics/renderers/GameRenderer.cpp @@ -1090,16 +1090,20 @@ void GameRenderer::renderPlayingState( const SDL_Color headerColor{255, 220, 0, 255}; const SDL_Color textColor{200, 220, 235, 200}; const SDL_Color mutedColor{150, 180, 200, 180}; - pixelFont->draw(renderer, statsX + 12.0f, statsY + 8.0f, "STATISTICS", 0.92f, headerColor); + pixelFont->draw(renderer, statsX + 12.0f, statsY + 8.0f, "STATISTICS", 0.46f, headerColor); // Tighter spacing and smaller icons/text for compact analytics console - float yCursor = statsY + 36.0f; - const float leftPad = 12.0f; + float yCursor = statsY + 34.0f; + const float leftPad = 2.0f; const float rightPad = 14.0f; - // Increase row gap to avoid icon overlap on smaller scales - const float rowGap = 20.0f; + // Increase row gap to avoid icon overlap on smaller scales (bumped up) + const float rowGap = 28.0f; const float barHeight = 2.0f; + // Text scales for per-row numbers (slightly larger than before) + const float countScale = 0.45f; + const float percScale = 0.43f; + // Determine max percent to highlight top used piece int maxPerc = 0; for (int i = 0; i < PIECE_COUNT; ++i) { @@ -1109,24 +1113,29 @@ void GameRenderer::renderPlayingState( // Row order groups: first 4, then last 3 std::vector order = {0,1,2,3, 4,5,6}; + // Precompute max widths for counts/perc so right-alignment is stable + int maxCountW = 0, maxCountH = 0; + int maxPercW = 0, maxPercH = 0; + for (int oi : order) { + char tmpCount[16]; snprintf(tmpCount, sizeof(tmpCount), "%dx", blockCounts[oi]); + char tmpPerc[16]; int tmpPercVal = (totalBlocks > 0) ? int(std::round(100.0 * double(blockCounts[oi]) / double(totalBlocks))) : 0; snprintf(tmpPerc, sizeof(tmpPerc), "%d%%", tmpPercVal); + pixelFont->measure(tmpCount, countScale, maxCountW, maxCountH); + int pw=0, ph=0; pixelFont->measure(tmpPerc, percScale, pw, ph); + maxPercW = std::max(maxPercW, pw); + maxPercH = std::max(maxPercH, ph); + } + for (size_t idx = 0; idx < order.size(); ++idx) { int i = order[idx]; float rowLeft = statsX + leftPad; float rowRight = statsX + statsW - rightPad; - // Icon card with a small backing to match the reference layout + // Icon aligned left, slightly higher to match reference spacing float iconSize = finalBlockSize * 0.52f; float iconBgPad = 6.0f; - float iconBgW = iconSize * 3.0f + iconBgPad * 2.0f; - float iconBgH = iconSize * 3.0f + iconBgPad * 2.0f; - float iconBgX = rowLeft - 6.0f; + float iconBgX = rowLeft - 18.0f; float iconBgY = yCursor - 10.0f; - SDL_SetRenderDrawColor(renderer, 14, 20, 32, 210); - SDL_FRect iconBg{iconBgX, iconBgY, iconBgW, iconBgH}; - SDL_RenderFillRect(renderer, &iconBg); - SDL_SetRenderDrawColor(renderer, 40, 70, 110, 180); - SDL_RenderRect(renderer, &iconBg); // Measure right-side text first so we can vertically align icon with text int count = blockCounts[i]; @@ -1134,14 +1143,14 @@ void GameRenderer::renderPlayingState( int perc = (totalBlocks > 0) ? int(std::round(100.0 * double(count) / double(totalBlocks))) : 0; char percStr[16]; snprintf(percStr, sizeof(percStr), "%d%%", perc); - int countW=0, countH=0; pixelFont->measure(countStr, 0.82f, countW, countH); - int percW=0, percH=0; pixelFont->measure(percStr, 0.78f, percW, percH); + int countW = maxCountW, countH = maxCountH; + int percW = maxPercW, percH = maxPercH; float iconX = iconBgX + iconBgPad; - float iconY = iconBgY + iconBgPad + 2.0f; + float iconY = yCursor - 6.0f + ((float)countH - iconSize) * 0.5f; drawSmallPiece(renderer, blocksTex, static_cast(i), iconX, iconY, iconSize); - // Badge for counts/percent so text sits on a soft dark backing + // Badge for counts/percent with no background, aligned to the right const float numbersGap = 14.0f; const float numbersPadX = 10.0f; const float numbersPadY = 6.0f; @@ -1151,20 +1160,17 @@ void GameRenderer::renderPlayingState( float numbersX = rowRight - numbersW; float numbersY = yCursor - (numbersH - static_cast(maxTextH)) * 0.5f; - SDL_SetRenderDrawColor(renderer, 32, 44, 60, 210); - SDL_FRect numbersBg{numbersX, numbersY, numbersW, numbersH}; - SDL_RenderFillRect(renderer, &numbersBg); - float textY = numbersY + (numbersH - static_cast(maxTextH)) * 0.5f; - float countX = numbersX + numbersPadX; + // Right-align the numbers block: perc anchored to the right, count right-aligned to the perc with gap float percX = numbersX + numbersW - percW - numbersPadX; - pixelFont->draw(renderer, countX, textY, countStr, 0.82f, textColor); - pixelFont->draw(renderer, percX, textY, percStr, 0.78f, mutedColor); + float countX = percX - numbersGap - countW; + pixelFont->draw(renderer, countX, textY, countStr, countScale, textColor); + pixelFont->draw(renderer, percX, textY, percStr, percScale, mutedColor); - // Progress bar anchored to the numbers badge, matching the reference width + // Progress bar anchored to the numbers width float barX = numbersX; float barW = numbersW; - float barY = numbersY + numbersH + 10.0f; + float barY = numbersY + numbersH + 8.0f; SDL_SetRenderDrawColor(renderer, 24, 80, 120, 220); SDL_FRect track{barX, barY, barW, barHeight}; @@ -1186,15 +1192,8 @@ void GameRenderer::renderPlayingState( SDL_FRect fill{barX, barY, fillW, barHeight}; SDL_RenderFillRect(renderer, &fill); - // Advance cursor to next row: after bar + gap (leave 20px space before next block) - yCursor = barY + barHeight + rowGap; - if (idx == 3) { - // faint separator - SDL_SetRenderDrawColor(renderer, 60, 80, 140, 90); - SDL_FRect sep{statsX + 8.0f, yCursor, statsW - 16.0f, 1.5f}; - SDL_RenderFillRect(renderer, &sep); - yCursor += 8.0f; - } + // Advance cursor to next row: after bar + gap (leave more space between blocks) + yCursor = barY + barHeight + rowGap + 6.0f; } // Bottom summary stats @@ -1211,20 +1210,20 @@ void GameRenderer::renderPlayingState( const float valueRightPad = 12.0f; // pad from right edge int valW=0, valH=0; - pixelFont->measure(totalStr, 0.82f, valW, valH); + pixelFont->measure(totalStr, 0.41f, valW, valH); float totalX = statsX + statsW - valueRightPad - (float)valW; - pixelFont->draw(renderer, labelX, summaryY + 0.0f, "TOTAL PIECES", 0.72f, labelMuted); - pixelFont->draw(renderer, totalX, summaryY + 0.0f, totalStr, 0.82f, summaryValueColor); + pixelFont->draw(renderer, labelX, summaryY + 0.0f, "TOTAL PIECES", 0.36f, labelMuted); + pixelFont->draw(renderer, totalX, summaryY + 0.0f, totalStr, 0.41f, summaryValueColor); - pixelFont->measure(tetrisesStr, 0.82f, valW, valH); + pixelFont->measure(tetrisesStr, 0.41f, valW, valH); float tetrisesX = statsX + statsW - valueRightPad - (float)valW; - pixelFont->draw(renderer, labelX, summaryY + 22.0f, "TETRISES MADE", 0.72f, labelMuted); - pixelFont->draw(renderer, tetrisesX, summaryY + 22.0f, tetrisesStr, 0.82f, summaryValueColor); + pixelFont->draw(renderer, labelX, summaryY + 22.0f, "TETRISES MADE", 0.36f, labelMuted); + pixelFont->draw(renderer, tetrisesX, summaryY + 22.0f, tetrisesStr, 0.41f, summaryValueColor); - pixelFont->measure(maxComboStr, 0.82f, valW, valH); + pixelFont->measure(maxComboStr, 0.41f, valW, valH); float comboX = statsX + statsW - valueRightPad - (float)valW; - pixelFont->draw(renderer, labelX, summaryY + 44.0f, "MAX COMBO", 0.72f, labelMuted); - pixelFont->draw(renderer, comboX, summaryY + 44.0f, maxComboStr, 0.82f, summaryValueColor); + pixelFont->draw(renderer, labelX, summaryY + 44.0f, "MAX COMBO", 0.36f, labelMuted); + pixelFont->draw(renderer, comboX, summaryY + 44.0f, maxComboStr, 0.41f, summaryValueColor); // Draw score panel (right side) const float contentTopOffset = 0.0f;