upodate game start and blur on pause
This commit is contained in:
@ -122,10 +122,7 @@ void GameRenderer::renderPlayingState(
|
||||
float logicalH,
|
||||
float logicalScale,
|
||||
float winW,
|
||||
float winH,
|
||||
bool showExitConfirmPopup,
|
||||
int exitPopupSelectedButton,
|
||||
bool suppressPauseVisuals
|
||||
float winH
|
||||
) {
|
||||
if (!game || !pixelFont) return;
|
||||
|
||||
@ -238,7 +235,7 @@ void GameRenderer::renderPlayingState(
|
||||
}
|
||||
}
|
||||
|
||||
bool allowActivePieceRender = !game->isPaused() || suppressPauseVisuals;
|
||||
bool allowActivePieceRender = true;
|
||||
|
||||
// Draw ghost piece (where current piece will land)
|
||||
if (allowActivePieceRender) {
|
||||
@ -428,150 +425,177 @@ void GameRenderer::renderPlayingState(
|
||||
drawSmallPiece(renderer, blocksTex, static_cast<PieceType>(game->held().type), statsX + 60, statsY + statsH - 80, finalBlockSize * 0.6f);
|
||||
}
|
||||
|
||||
// Pause overlay (skip when visuals are suppressed, e.g., countdown)
|
||||
if (!suppressPauseVisuals && game->isPaused() && !showExitConfirmPopup) {
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
||||
|
||||
// Draw blur effect around the grid (keep in logical coordinates)
|
||||
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);
|
||||
}
|
||||
// Pause overlay logic moved to renderPauseOverlay
|
||||
|
||||
// Switch to window coordinates for the full-screen overlay and text
|
||||
SDL_Rect oldViewport;
|
||||
SDL_GetRenderViewport(renderer, &oldViewport);
|
||||
float oldScaleX, oldScaleY;
|
||||
SDL_GetRenderScale(renderer, &oldScaleX, &oldScaleY);
|
||||
|
||||
SDL_SetRenderViewport(renderer, nullptr);
|
||||
SDL_SetRenderScale(renderer, 1.0f, 1.0f);
|
||||
|
||||
// Draw full screen overlay
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 180);
|
||||
SDL_FRect pauseOverlay{0, 0, winW, winH};
|
||||
SDL_RenderFillRect(renderer, &pauseOverlay);
|
||||
|
||||
// Draw centered text
|
||||
// Note: We multiply font scale by logicalScale to maintain consistent size
|
||||
// since we reset the renderer scale to 1.0
|
||||
const char* pausedText = "PAUSED";
|
||||
float pausedScale = 2.0f * logicalScale;
|
||||
int pW = 0, pH = 0;
|
||||
pixelFont->measure(pausedText, pausedScale, pW, pH);
|
||||
pixelFont->draw(renderer, (winW - pW) * 0.5f, (winH - pH) * 0.5f - (20 * logicalScale), pausedText, pausedScale, {255, 255, 255, 255});
|
||||
|
||||
const char* resumeText = "Press P to resume";
|
||||
float resumeScale = 0.8f * logicalScale;
|
||||
int rW = 0, rH = 0;
|
||||
pixelFont->measure(resumeText, resumeScale, rW, rH);
|
||||
pixelFont->draw(renderer, (winW - rW) * 0.5f, (winH - pH) * 0.5f + (40 * logicalScale), resumeText, resumeScale, {200, 200, 220, 255});
|
||||
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
|
||||
|
||||
// Restore previous render state
|
||||
SDL_SetRenderViewport(renderer, &oldViewport);
|
||||
SDL_SetRenderScale(renderer, oldScaleX, oldScaleY);
|
||||
}
|
||||
|
||||
// Exit confirmation popup styled like other retro panels
|
||||
if (showExitConfirmPopup) {
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 200);
|
||||
SDL_FRect fullWin{0.f, 0.f, winW, winH};
|
||||
SDL_RenderFillRect(renderer, &fullWin);
|
||||
|
||||
const float panelW = 640.0f;
|
||||
const float panelH = 320.0f;
|
||||
SDL_FRect panel{
|
||||
(logicalW - panelW) * 0.5f + contentOffsetX,
|
||||
(logicalH - panelH) * 0.5f + contentOffsetY,
|
||||
panelW,
|
||||
panelH
|
||||
};
|
||||
|
||||
SDL_FRect shadow{panel.x + 6.0f, panel.y + 10.0f, panel.w, panel.h};
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 140);
|
||||
SDL_RenderFillRect(renderer, &shadow);
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
SDL_FRect glow{panel.x - float(i * 2), panel.y - float(i * 2), panel.w + float(i * 4), panel.h + float(i * 4)};
|
||||
SDL_SetRenderDrawColor(renderer, 0, 180, 255, Uint8(44 - i * 7));
|
||||
SDL_RenderRect(renderer, &glow);
|
||||
}
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 18, 30, 52, 255);
|
||||
SDL_RenderFillRect(renderer, &panel);
|
||||
SDL_SetRenderDrawColor(renderer, 70, 120, 210, 255);
|
||||
SDL_RenderRect(renderer, &panel);
|
||||
|
||||
SDL_FRect inner{panel.x + 24.0f, panel.y + 98.0f, panel.w - 48.0f, panel.h - 146.0f};
|
||||
SDL_SetRenderDrawColor(renderer, 16, 24, 40, 235);
|
||||
SDL_RenderFillRect(renderer, &inner);
|
||||
SDL_SetRenderDrawColor(renderer, 40, 80, 140, 235);
|
||||
SDL_RenderRect(renderer, &inner);
|
||||
|
||||
const std::string title = "EXIT GAME?";
|
||||
int titleW = 0, titleH = 0;
|
||||
const float titleScale = 1.8f;
|
||||
pixelFont->measure(title, titleScale, titleW, titleH);
|
||||
pixelFont->draw(renderer, panel.x + (panel.w - titleW) * 0.5f, panel.y + 30.0f, title, titleScale, {255, 230, 140, 255});
|
||||
|
||||
std::array<std::string, 2> lines = {
|
||||
"Are you sure you want to quit?",
|
||||
"Current progress will be lost."
|
||||
};
|
||||
float lineY = inner.y + 22.0f;
|
||||
const float lineScale = 1.05f;
|
||||
for (const auto& line : lines) {
|
||||
int lineW = 0, lineH = 0;
|
||||
pixelFont->measure(line, lineScale, lineW, lineH);
|
||||
float textX = panel.x + (panel.w - lineW) * 0.5f;
|
||||
pixelFont->draw(renderer, textX, lineY, line, lineScale, SDL_Color{210, 220, 240, 255});
|
||||
lineY += lineH + 10.0f;
|
||||
}
|
||||
|
||||
const float horizontalPad = 28.0f;
|
||||
const float buttonGap = 32.0f;
|
||||
const float buttonH = 66.0f;
|
||||
float buttonW = (inner.w - horizontalPad * 2.0f - buttonGap) * 0.5f;
|
||||
float buttonY = inner.y + inner.h - buttonH - 24.0f;
|
||||
|
||||
auto drawButton = [&](int idx, float x, const char* label) {
|
||||
bool selected = (exitPopupSelectedButton == idx);
|
||||
SDL_Color base = (idx == 0) ? SDL_Color{185, 70, 70, 255} : SDL_Color{60, 95, 150, 255};
|
||||
SDL_Color body = selected ? SDL_Color{Uint8(std::min(255, base.r + 35)), Uint8(std::min(255, base.g + 35)), Uint8(std::min(255, base.b + 35)), 255} : base;
|
||||
SDL_Color border = selected ? SDL_Color{255, 220, 120, 255} : SDL_Color{80, 110, 160, 255};
|
||||
|
||||
SDL_FRect btn{x, buttonY, buttonW, buttonH};
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 120);
|
||||
SDL_FRect btnShadow{btn.x + 4.0f, btn.y + 6.0f, btn.w, btn.h};
|
||||
SDL_RenderFillRect(renderer, &btnShadow);
|
||||
SDL_SetRenderDrawColor(renderer, body.r, body.g, body.b, body.a);
|
||||
SDL_RenderFillRect(renderer, &btn);
|
||||
SDL_SetRenderDrawColor(renderer, border.r, border.g, border.b, border.a);
|
||||
SDL_RenderRect(renderer, &btn);
|
||||
|
||||
int textW = 0, textH = 0;
|
||||
const float labelScale = 1.4f;
|
||||
pixelFont->measure(label, labelScale, textW, textH);
|
||||
float textX = btn.x + (btn.w - textW) * 0.5f;
|
||||
float textY = btn.y + (btn.h - textH) * 0.5f;
|
||||
SDL_Color textColor = selected ? SDL_Color{255, 255, 255, 255} : SDL_Color{230, 235, 250, 255};
|
||||
pixelFont->draw(renderer, textX, textY, label, labelScale, textColor);
|
||||
};
|
||||
|
||||
float yesX = inner.x + horizontalPad;
|
||||
float noX = yesX + buttonW + buttonGap;
|
||||
drawButton(0, yesX, "YES");
|
||||
drawButton(1, noX, "NO");
|
||||
}
|
||||
// Exit popup logic moved to renderExitPopup
|
||||
}
|
||||
|
||||
void GameRenderer::renderExitPopup(
|
||||
SDL_Renderer* renderer,
|
||||
FontAtlas* pixelFont,
|
||||
float winW,
|
||||
float winH,
|
||||
float logicalScale,
|
||||
int selectedButton
|
||||
) {
|
||||
// Calculate content offsets (same as in renderPlayingState for consistency)
|
||||
// We need to re-calculate them or pass them in?
|
||||
// The popup uses logical coordinates centered on screen.
|
||||
// Let's use the same logic as renderPauseOverlay (window coordinates) to be safe and consistent?
|
||||
// The original code used logical coordinates + contentOffset.
|
||||
// Let's stick to the original look but render it in window coordinates to ensure it covers everything properly.
|
||||
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
||||
|
||||
// Switch to window coordinates
|
||||
SDL_Rect oldViewport;
|
||||
SDL_GetRenderViewport(renderer, &oldViewport);
|
||||
float oldScaleX, oldScaleY;
|
||||
SDL_GetRenderScale(renderer, &oldScaleX, &oldScaleY);
|
||||
|
||||
SDL_SetRenderViewport(renderer, nullptr);
|
||||
SDL_SetRenderScale(renderer, 1.0f, 1.0f);
|
||||
|
||||
// Full screen dim
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 200);
|
||||
SDL_FRect fullWin{0.f, 0.f, winW, winH};
|
||||
SDL_RenderFillRect(renderer, &fullWin);
|
||||
|
||||
// Calculate panel position (centered in window)
|
||||
// Original was logicalW based, let's map it to window size.
|
||||
// Logical 640x320 scaled up.
|
||||
float panelW = 640.0f * logicalScale;
|
||||
float panelH = 320.0f * logicalScale;
|
||||
float panelX = (winW - panelW) * 0.5f;
|
||||
float panelY = (winH - panelH) * 0.5f;
|
||||
|
||||
SDL_FRect panel{panelX, panelY, panelW, panelH};
|
||||
|
||||
SDL_FRect shadow{panel.x + 6.0f * logicalScale, panel.y + 10.0f * logicalScale, panel.w, panel.h};
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 140);
|
||||
SDL_RenderFillRect(renderer, &shadow);
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
float off = float(i * 2) * logicalScale;
|
||||
float exp = float(i * 4) * logicalScale;
|
||||
SDL_FRect glow{panel.x - off, panel.y - off, panel.w + exp, panel.h + exp};
|
||||
SDL_SetRenderDrawColor(renderer, 0, 180, 255, Uint8(44 - i * 7));
|
||||
SDL_RenderRect(renderer, &glow);
|
||||
}
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 18, 30, 52, 255);
|
||||
SDL_RenderFillRect(renderer, &panel);
|
||||
SDL_SetRenderDrawColor(renderer, 70, 120, 210, 255);
|
||||
SDL_RenderRect(renderer, &panel);
|
||||
|
||||
SDL_FRect inner{panel.x + 24.0f * logicalScale, panel.y + 98.0f * logicalScale, panel.w - 48.0f * logicalScale, panel.h - 146.0f * logicalScale};
|
||||
SDL_SetRenderDrawColor(renderer, 16, 24, 40, 235);
|
||||
SDL_RenderFillRect(renderer, &inner);
|
||||
SDL_SetRenderDrawColor(renderer, 40, 80, 140, 235);
|
||||
SDL_RenderRect(renderer, &inner);
|
||||
|
||||
const std::string title = "EXIT GAME?";
|
||||
int titleW = 0, titleH = 0;
|
||||
const float titleScale = 1.8f * logicalScale;
|
||||
pixelFont->measure(title, titleScale, titleW, titleH);
|
||||
pixelFont->draw(renderer, panel.x + (panel.w - titleW) * 0.5f, panel.y + 30.0f * logicalScale, title, titleScale, {255, 230, 140, 255});
|
||||
|
||||
std::array<std::string, 2> lines = {
|
||||
"Are you sure you want to quit?",
|
||||
"Current progress will be lost."
|
||||
};
|
||||
float lineY = inner.y + 22.0f * logicalScale;
|
||||
const float lineScale = 1.05f * logicalScale;
|
||||
for (const auto& line : lines) {
|
||||
int lineW = 0, lineH = 0;
|
||||
pixelFont->measure(line, lineScale, lineW, lineH);
|
||||
float textX = panel.x + (panel.w - lineW) * 0.5f;
|
||||
pixelFont->draw(renderer, textX, lineY, line, lineScale, SDL_Color{210, 220, 240, 255});
|
||||
lineY += lineH + 10.0f * logicalScale;
|
||||
}
|
||||
|
||||
const float horizontalPad = 28.0f * logicalScale;
|
||||
const float buttonGap = 32.0f * logicalScale;
|
||||
const float buttonH = 66.0f * logicalScale;
|
||||
float buttonW = (inner.w - horizontalPad * 2.0f - buttonGap) * 0.5f;
|
||||
float buttonY = inner.y + inner.h - buttonH - 24.0f * logicalScale;
|
||||
|
||||
auto drawButton = [&](int idx, float x, const char* label) {
|
||||
bool selected = (selectedButton == idx);
|
||||
SDL_Color base = (idx == 0) ? SDL_Color{185, 70, 70, 255} : SDL_Color{60, 95, 150, 255};
|
||||
SDL_Color body = selected ? SDL_Color{Uint8(std::min(255, base.r + 35)), Uint8(std::min(255, base.g + 35)), Uint8(std::min(255, base.b + 35)), 255} : base;
|
||||
SDL_Color border = selected ? SDL_Color{255, 220, 120, 255} : SDL_Color{80, 110, 160, 255};
|
||||
|
||||
SDL_FRect btn{x, buttonY, buttonW, buttonH};
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 120);
|
||||
SDL_FRect btnShadow{btn.x + 4.0f * logicalScale, btn.y + 6.0f * logicalScale, btn.w, btn.h};
|
||||
SDL_RenderFillRect(renderer, &btnShadow);
|
||||
SDL_SetRenderDrawColor(renderer, body.r, body.g, body.b, body.a);
|
||||
SDL_RenderFillRect(renderer, &btn);
|
||||
SDL_SetRenderDrawColor(renderer, border.r, border.g, border.b, border.a);
|
||||
SDL_RenderRect(renderer, &btn);
|
||||
|
||||
int textW = 0, textH = 0;
|
||||
const float labelScale = 1.4f * logicalScale;
|
||||
pixelFont->measure(label, labelScale, textW, textH);
|
||||
float textX = btn.x + (btn.w - textW) * 0.5f;
|
||||
float textY = btn.y + (btn.h - textH) * 0.5f;
|
||||
SDL_Color textColor = selected ? SDL_Color{255, 255, 255, 255} : SDL_Color{230, 235, 250, 255};
|
||||
pixelFont->draw(renderer, textX, textY, label, labelScale, textColor);
|
||||
};
|
||||
|
||||
float yesX = inner.x + horizontalPad;
|
||||
float noX = yesX + buttonW + buttonGap;
|
||||
drawButton(0, yesX, "YES");
|
||||
drawButton(1, noX, "NO");
|
||||
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
|
||||
|
||||
// Restore previous render state
|
||||
SDL_SetRenderViewport(renderer, &oldViewport);
|
||||
SDL_SetRenderScale(renderer, oldScaleX, oldScaleY);
|
||||
}
|
||||
|
||||
void GameRenderer::renderPauseOverlay(
|
||||
SDL_Renderer* renderer,
|
||||
FontAtlas* pixelFont,
|
||||
float winW,
|
||||
float winH,
|
||||
float logicalScale
|
||||
) {
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
||||
|
||||
// Switch to window coordinates for the full-screen overlay and text
|
||||
SDL_Rect oldViewport;
|
||||
SDL_GetRenderViewport(renderer, &oldViewport);
|
||||
float oldScaleX, oldScaleY;
|
||||
SDL_GetRenderScale(renderer, &oldScaleX, &oldScaleY);
|
||||
|
||||
SDL_SetRenderViewport(renderer, nullptr);
|
||||
SDL_SetRenderScale(renderer, 1.0f, 1.0f);
|
||||
|
||||
// Draw full screen overlay (darken)
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 180);
|
||||
SDL_FRect pauseOverlay{0, 0, winW, winH};
|
||||
SDL_RenderFillRect(renderer, &pauseOverlay);
|
||||
|
||||
// Draw centered text
|
||||
const char* pausedText = "PAUSED";
|
||||
float pausedScale = 2.0f * logicalScale;
|
||||
int pW = 0, pH = 0;
|
||||
pixelFont->measure(pausedText, pausedScale, pW, pH);
|
||||
pixelFont->draw(renderer, (winW - pW) * 0.5f, (winH - pH) * 0.5f - (20 * logicalScale), pausedText, pausedScale, {255, 255, 255, 255});
|
||||
|
||||
const char* resumeText = "Press P to resume";
|
||||
float resumeScale = 0.8f * logicalScale;
|
||||
int rW = 0, rH = 0;
|
||||
pixelFont->measure(resumeText, resumeScale, rW, rH);
|
||||
pixelFont->draw(renderer, (winW - rW) * 0.5f, (winH - pH) * 0.5f + (40 * logicalScale), resumeText, resumeScale, {200, 200, 220, 255});
|
||||
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
|
||||
|
||||
// Restore previous render state
|
||||
SDL_SetRenderViewport(renderer, &oldViewport);
|
||||
SDL_SetRenderScale(renderer, oldScaleX, oldScaleY);
|
||||
}
|
||||
|
||||
@ -25,10 +25,26 @@ public:
|
||||
float logicalH,
|
||||
float logicalScale,
|
||||
float winW,
|
||||
float winH
|
||||
);
|
||||
|
||||
// Render the pause overlay (full screen)
|
||||
static void renderPauseOverlay(
|
||||
SDL_Renderer* renderer,
|
||||
FontAtlas* pixelFont,
|
||||
float winW,
|
||||
float winH,
|
||||
bool showExitConfirmPopup,
|
||||
int exitPopupSelectedButton = 1, // 0=YES, 1=NO
|
||||
bool suppressPauseVisuals = false
|
||||
float logicalScale
|
||||
);
|
||||
|
||||
// Render the exit confirmation popup
|
||||
static void renderExitPopup(
|
||||
SDL_Renderer* renderer,
|
||||
FontAtlas* pixelFont,
|
||||
float winW,
|
||||
float winH,
|
||||
float logicalScale,
|
||||
int selectedButton
|
||||
);
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user