refactor hold element drawing

This commit is contained in:
2025-12-20 11:22:18 +01:00
parent a520de6c1f
commit 212dd4c404

View File

@ -116,6 +116,79 @@ void GameRenderer::drawSmallPiece(SDL_Renderer* renderer, SDL_Texture* blocksTex
} }
} }
// Draw the hold panel (extracted for readability).
static void drawHoldPanel(SDL_Renderer* renderer,
Game* game,
FontAtlas* pixelFont,
SDL_Texture* blocksTex,
SDL_Texture* holdPanelTex,
float scoreX,
float statsW,
float gridY,
float finalBlockSize,
float statsY,
float statsH) {
float holdBlockH = (finalBlockSize * 0.6f) * 4.0f;
// Base panel height; enforce minimum but allow larger to fit texture
float panelH = std::max(holdBlockH + 12.0f, 420.0f);
// Increase height by ~20% of the hold block to give more vertical room
float extraH = holdBlockH * 0.20f;
panelH += extraH;
const float holdGap = 18.0f;
// Align X to the bottom score label (`scoreX`) plus an offset to the right
float panelX = scoreX + 30.0f; // move ~30px right to align with score label
float panelW = statsW + 32.0f;
float panelY = gridY - panelH - holdGap;
// Move panel a bit higher for spacing (about half the extra height)
panelY -= extraH * 0.5f;
float labelX = panelX + 40.0f; // shift HOLD label ~30px to the right
float labelY = panelY + 8.0f;
if (holdPanelTex) {
int texW = 0, texH = 0;
SDL_QueryTexture(holdPanelTex, nullptr, nullptr, &texW, &texH);
if (texW > 0 && texH > 0) {
// Fill panel width and compute destination height from texture aspect ratio
float texAspect = float(texH) / float(texW);
float dstW = panelW;
float dstH = dstW * texAspect;
// If texture height exceeds panel, expand panelH to fit texture comfortably
if (dstH + 12.0f > panelH) {
panelH = dstH + 12.0f;
panelY = gridY - panelH - holdGap;
labelY = panelY + 8.0f;
}
float dstX = panelX;
float dstY = panelY + (panelH - dstH) * 0.5f;
SDL_FRect panelDst{dstX, dstY, dstW, dstH};
SDL_SetTextureBlendMode(holdPanelTex, SDL_BLENDMODE_BLEND);
SDL_SetTextureScaleMode(holdPanelTex, SDL_SCALEMODE_LINEAR);
SDL_RenderTexture(renderer, holdPanelTex, nullptr, &panelDst);
} else {
// Fallback to filling panel area if texture metrics unavailable
SDL_SetRenderDrawColor(renderer, 12, 18, 32, 220);
SDL_FRect panelDst{panelX, panelY, panelW, panelH};
SDL_RenderFillRect(renderer, &panelDst);
}
} else {
SDL_SetRenderDrawColor(renderer, 12, 18, 32, 220);
SDL_FRect panelDst{panelX, panelY, panelW, panelH};
SDL_RenderFillRect(renderer, &panelDst);
}
pixelFont->draw(renderer, labelX, labelY, "HOLD", 1.0f, {255, 220, 0, 255});
if (game->held().type < PIECE_COUNT) {
float previewW = finalBlockSize * 0.6f * 4.0f;
float previewX = panelX + (panelW - previewW) * 0.5f;
float previewY = panelY + (panelH - holdBlockH) * 0.5f;
drawSmallPiece(renderer, blocksTex, static_cast<PieceType>(game->held().type), previewX, previewY, finalBlockSize * 0.6f);
}
}
void GameRenderer::renderPlayingState( void GameRenderer::renderPlayingState(
SDL_Renderer* renderer, SDL_Renderer* renderer,
Game* game, Game* game,
@ -165,64 +238,8 @@ void GameRenderer::renderPlayingState(
const float availableHeight = logicalH - TOP_MARGIN - BOTTOM_MARGIN - NEXT_PIECE_HEIGHT; const float availableHeight = logicalH - TOP_MARGIN - BOTTOM_MARGIN - NEXT_PIECE_HEIGHT;
const float maxBlockSizeW = availableWidth / Game::COLS; const float maxBlockSizeW = availableWidth / Game::COLS;
const float maxBlockSizeH = availableHeight / Game::ROWS; // Draw hold panel via helper
float previewY = rowTop - 4.0f; drawHoldPanel(renderer, game, pixelFont, blocksTex, holdPanelTex, scoreX, statsW, gridY, finalBlockSize, statsY, statsH);
const float finalBlockSize = std::max(20.0f, std::min(BLOCK_SIZE, 40.0f));
const float GRID_W = Game::COLS * finalBlockSize;
const float GRID_H = Game::ROWS * finalBlockSize;
// Calculate positions
const float totalContentHeight = NEXT_PIECE_HEIGHT + GRID_H;
const float availableVerticalSpace = logicalH - TOP_MARGIN - BOTTOM_MARGIN;
const float verticalCenterOffset = (availableVerticalSpace - totalContentHeight) * 0.5f;
const float contentStartY = TOP_MARGIN + verticalCenterOffset;
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;
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;
const float nextY = contentStartY + contentOffsetY;
// Handle line clearing effects
if (game->hasCompletedLines() && lineEffect && !lineEffect->isActive()) {
auto completedLines = game->getCompletedLines();
lineEffect->startLineClear(completedLines, static_cast<int>(gridX), static_cast<int>(gridY), static_cast<int>(finalBlockSize));
}
// 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);
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 (solid so grid remains legible over background) // Draw grid lines (solid so grid remains legible over background)
SDL_SetRenderDrawColor(renderer, 40, 45, 60, 255); SDL_SetRenderDrawColor(renderer, 40, 45, 60, 255);
@ -529,7 +546,7 @@ void GameRenderer::renderPlayingState(
SDL_RenderFillRect(renderer, &panelDst); SDL_RenderFillRect(renderer, &panelDst);
} }
pixelFont->draw(renderer, labelX, labelY, "HOLDx", 1.0f, {255, 220, 0, 255}); pixelFont->draw(renderer, labelX, labelY, "HOLD", 1.0f, {255, 220, 0, 255});
if (game->held().type < PIECE_COUNT) { if (game->held().type < PIECE_COUNT) {
float previewW = finalBlockSize * 0.6f * 4.0f; float previewW = finalBlockSize * 0.6f * 4.0f;