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(
|
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;
|
||||||
|
|||||||
Reference in New Issue
Block a user