fix sidebar statistics

This commit is contained in:
2025-11-22 20:53:26 +01:00
parent 3c3a85d6d4
commit 28dd513619
2 changed files with 194 additions and 137 deletions

View File

@ -152,13 +152,13 @@ void GameRenderer::renderPlayingState(
const float NEXT_PIECE_HEIGHT = 120.0f;
const float BOTTOM_MARGIN = 60.0f;
// Calculate layout dimensions
float yCursor = statsY + 44.0f;
const float availableWidth = logicalW - (MIN_MARGIN * 2) - (PANEL_WIDTH * 2) - (PANEL_SPACING * 2);
const float availableHeight = logicalH - TOP_MARGIN - BOTTOM_MARGIN - NEXT_PIECE_HEIGHT;
const float maxBlockSizeW = availableWidth / Game::COLS;
const float maxBlockSizeH = availableHeight / Game::ROWS;
const float BLOCK_SIZE = std::min(maxBlockSizeW, maxBlockSizeH);
float previewY = rowTop - 4.0f;
const float finalBlockSize = std::max(20.0f, std::min(BLOCK_SIZE, 40.0f));
const float GRID_W = Game::COLS * finalBlockSize;
@ -172,17 +172,17 @@ void GameRenderer::renderPlayingState(
const float totalLayoutWidth = PANEL_WIDTH + PANEL_SPACING + GRID_W + PANEL_SPACING + PANEL_WIDTH;
const float layoutStartX = (logicalW - totalLayoutWidth) * 0.5f;
float barY = previewY + previewSize + 10.0f;
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;
const float statsW = PANEL_WIDTH;
const float statsH = GRID_H;
// Next piece preview position
float rowBottom = percY + 14.0f;
SDL_FRect rowBg{
previewX - 10.0f,
rowTop - 8.0f,
rowWidth + 20.0f,
rowBottom - rowTop
};
const float nextW = finalBlockSize * 4 + 20;
const float nextH = finalBlockSize * 2 + 20;
const float nextX = gridX + (GRID_W - nextW) * 0.5f;
@ -283,7 +283,7 @@ void GameRenderer::renderPlayingState(
if (lineEffect && lineEffect->isActive()) {
lineEffect->render(renderer, static_cast<int>(gridX), static_cast<int>(gridY), static_cast<int>(finalBlockSize));
}
float yCursor = statsY + 44.0f;
// Draw next piece preview
pixelFont->draw(renderer, nextX + 10, nextY - 20, "NEXT", 1.0f, {255, 220, 0, 255});
if (game->next().type < PIECE_COUNT) {
@ -294,66 +294,82 @@ void GameRenderer::renderPlayingState(
pixelFont->draw(renderer, statsX + 10, statsY + 10, "BLOCKS", 1.0f, {255, 220, 0, 255});
const auto& blockCounts = game->getBlockCounts();
int totalBlocks = 0;
float previewY = rowTop - 4.0f;
for (int i = 0; i < PIECE_COUNT; ++i) totalBlocks += blockCounts[i];
const char* pieceNames[] = {"I", "O", "T", "S", "Z", "J", "L"};
float yCursor = statsY + 52;
const float rowPadding = 18.0f;
const float rowWidth = statsW - rowPadding * 2.0f;
const float rowSpacing = 12.0f;
float yCursor = statsY + 44.0f;
for (int i = 0; i < PIECE_COUNT; ++i) {
float py = yCursor;
// Draw small piece icon
float previewSize = finalBlockSize * 0.55f;
drawSmallPiece(renderer, blocksTex, static_cast<PieceType>(i), statsX + 18, py, previewSize);
// Compute preview height
float rowTop = yCursor;
float previewSize = finalBlockSize * 0.52f;
float previewX = statsX + rowPadding;
float previewY = rowTop - 14.0f;
// Determine actual piece height so bars never overlap blocks
Game::Piece previewPiece{};
previewPiece.type = static_cast<PieceType>(i);
previewPiece.rot = 0;
previewPiece.x = 0;
previewPiece.y = 0;
int maxCy = -1;
Game::Piece prev;
prev.type = static_cast<PieceType>(i);
prev.rot = 0;
prev.x = 0;
prev.y = 0;
for (int cy = 0; cy < 4; ++cy) {
for (int cx = 0; cx < 4; ++cx) {
if (Game::cellFilled(prev, cx, cy)) maxCy = std::max(maxCy, cy);
if (Game::cellFilled(previewPiece, cx, cy)) {
maxCy = std::max(maxCy, cy);
}
}
}
int tilesHigh = (maxCy >= 0 ? maxCy + 1 : 1);
float previewHeight = tilesHigh * previewSize;
// Count display
float pieceHeight = (maxCy >= 0 ? maxCy + 1.0f : 1.0f) * previewSize;
int count = blockCounts[i];
char countStr[16];
snprintf(countStr, sizeof(countStr), "%d", count);
pixelFont->draw(renderer, statsX + statsW - 20, py + 6, countStr, 1.1f, {240, 240, 245, 255});
// Percentage bar
int countW = 0, countH = 0;
pixelFont->measure(countStr, 1.0f, countW, countH);
float countX = previewX + rowWidth - static_cast<float>(countW);
float countY = previewY + 9.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 = statsX + 12;
float barY = py + previewHeight + 18.0f;
float barW = statsW - 24;
float barH = 6;
pixelFont->draw(renderer, barX, barY - 16, percStr, 0.8f, {230, 230, 235, 255});
// Progress bar
SDL_SetRenderDrawColor(renderer, 170, 170, 175, 200);
float barX = previewX;
float barY = previewY + pieceHeight + 12.0f;
float barH = 6.0f;
float barW = rowWidth;
float percY = barY + barH + 8.0f;
float fillW = barW * (perc / 100.0f);
fillW = std::clamp(fillW, 0.0f, barW);
float cardTop = rowTop - 14.0f;
float rowBottom = percY + 16.0f;
SDL_FRect rowBg{
previewX - 12.0f,
cardTop,
rowWidth + 24.0f,
rowBottom - cardTop
};
SDL_SetRenderDrawColor(renderer, 18, 26, 40, 200);
SDL_RenderFillRect(renderer, &rowBg);
SDL_SetRenderDrawColor(renderer, 70, 100, 150, 210);
SDL_RenderRect(renderer, &rowBg);
drawSmallPiece(renderer, blocksTex, static_cast<PieceType>(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_FRect track{barX, barY, barW, barH};
SDL_RenderFillRect(renderer, &track);
SDL_Color pc = COLORS[i + 1];
SDL_SetRenderDrawColor(renderer, pc.r, pc.g, pc.b, 230);
float fillW = barW * (perc / 100.0f);
if (fillW < 0) fillW = 0;
if (fillW > barW) fillW = barW;
SDL_SetRenderDrawColor(renderer, pc.r, pc.g, pc.b, 255);
SDL_FRect fill{barX, barY, fillW, barH};
SDL_RenderFillRect(renderer, &fill);
yCursor = barY + barH + 18.0f;
yCursor = rowBottom + rowSpacing;
}
// Draw score panel (right side)
@ -419,12 +435,26 @@ void GameRenderer::renderPlayingState(
// Pause overlay (suppressed when requested, e.g., countdown)
if (!suppressPauseVisuals && game->isPaused() && !showExitConfirmPopup) {
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
for (int i = -4; i <= 4; ++i) {
float spread = static_cast<float>(std::abs(i));
Uint8 alpha = Uint8(std::max(8.f, 32.f - spread * 4.f));
SDL_SetRenderDrawColor(renderer, 24, 32, 48, alpha);
SDL_FRect blurRect{
gridX - spread * 2.0f,
gridY - spread * 1.5f,
GRID_W + spread * 4.0f,
GRID_H + spread * 3.0f
};
SDL_RenderFillRect(renderer, &blurRect);
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 180);
SDL_FRect pauseOverlay{0, 0, logicalW, logicalH};
SDL_RenderFillRect(renderer, &pauseOverlay);
pixelFont->draw(renderer, logicalW * 0.5f - 80, logicalH * 0.5f - 20, "PAUSED", 2.0f, {255, 255, 255, 255});
pixelFont->draw(renderer, logicalW * 0.5f - 120, logicalH * 0.5f + 30, "Press P to resume", 0.8f, {200, 200, 220, 255});
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
}
if (showExitConfirmPopup) {