refactor hold element drawing
This commit is contained in:
@ -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(
|
||||
SDL_Renderer* renderer,
|
||||
Game* game,
|
||||
@ -165,64 +238,8 @@ void GameRenderer::renderPlayingState(
|
||||
const float availableHeight = logicalH - TOP_MARGIN - BOTTOM_MARGIN - NEXT_PIECE_HEIGHT;
|
||||
|
||||
const float maxBlockSizeW = availableWidth / Game::COLS;
|
||||
const float maxBlockSizeH = availableHeight / Game::ROWS;
|
||||
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;
|
||||
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 hold panel via helper
|
||||
drawHoldPanel(renderer, game, pixelFont, blocksTex, holdPanelTex, scoreX, statsW, gridY, finalBlockSize, statsY, statsH);
|
||||
|
||||
// Draw grid lines (solid so grid remains legible over background)
|
||||
SDL_SetRenderDrawColor(renderer, 40, 45, 60, 255);
|
||||
@ -529,7 +546,7 @@ void GameRenderer::renderPlayingState(
|
||||
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) {
|
||||
float previewW = finalBlockSize * 0.6f * 4.0f;
|
||||
|
||||
Reference in New Issue
Block a user