This commit is contained in:
2025-12-25 18:23:19 +01:00
parent 03bdc82dc1
commit 938988c876

View File

@ -831,6 +831,7 @@ void GameRenderer::renderPlayingState(
SDL_BlendMode oldBlend = SDL_BLENDMODE_NONE;
SDL_GetRenderDrawBlendMode(renderer, &oldBlend);
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
// rwrap already declared near function start; reuse it here.
// Add a small, smooth sub-pixel jitter to the starfield origin so the
// brightest star doesn't permanently sit exactly at the visual center.
{
@ -947,10 +948,10 @@ void GameRenderer::renderPlayingState(
float pulse = 0.5f + 0.5f * std::sin(sp.pulse);
Uint8 alpha = static_cast<Uint8>(std::clamp(lifeRatio * pulse, 0.0f, 1.0f) * 255.0f);
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(renderer, sp.color.r, sp.color.g, sp.color.b, alpha);
rwrap->setDrawColor(SDL_Color{sp.color.r, sp.color.g, sp.color.b, alpha});
float half = sp.size * 0.5f;
SDL_FRect fr{gridX + sp.x - half, gridY + sp.y - half, sp.size, sp.size};
SDL_RenderFillRect(renderer, &fr);
rwrap->fillRectF(&fr);
++it;
}
@ -964,10 +965,10 @@ void GameRenderer::renderPlayingState(
// If an external NEXT panel texture is used, skip the connector to avoid
// drawing a visible seam under the image/artwork.
if (!nextPanelTex) {
SDL_SetRenderDrawColor(renderer, 60, 80, 160, 255); // same as grid border
rwrap->setDrawColor(SDL_Color{60, 80, 160, 255}); // same as grid border
float connectorY = NEXT_PANEL_Y + NEXT_PANEL_HEIGHT; // bottom of next panel (near grid top)
SDL_FRect connRect{ NEXT_PANEL_X, connectorY - 1.0f, NEXT_PANEL_WIDTH, 2.0f };
SDL_RenderFillRect(renderer, &connRect);
rwrap->fillRectF(&connRect);
}
// Draw transport effect if active (renders the moving piece and trail)
@ -1178,27 +1179,27 @@ void GameRenderer::renderPlayingState(
}
if (asteroidsTex && spawnAlpha < 1.0f) {
SDL_SetTextureAlphaMod(asteroidsTex, static_cast<Uint8>(std::clamp(spawnAlpha, 0.0f, 1.0f) * 255.0f));
rwrap->setTextureAlphaMod(asteroidsTex, static_cast<Uint8>(std::clamp(spawnAlpha, 0.0f, 1.0f) * 255.0f));
}
float size = finalBlockSize * spawnScale * clearScale;
float offset = (finalBlockSize - size) * 0.5f;
if (asteroidsTex && clearAlpha < 1.0f) {
Uint8 alpha = static_cast<Uint8>(std::clamp(spawnAlpha * clearAlpha, 0.0f, 1.0f) * 255.0f);
SDL_SetTextureAlphaMod(asteroidsTex, alpha);
rwrap->setTextureAlphaMod(asteroidsTex, alpha);
}
drawAsteroid(renderer, asteroidsTex, bx + offset, by + offset, size, cell);
if (asteroidsTex && (spawnAlpha < 1.0f || clearAlpha < 1.0f)) {
SDL_SetTextureAlphaMod(asteroidsTex, 255);
rwrap->setTextureAlphaMod(asteroidsTex, 255);
}
} else {
if (blocksTex && clearAlpha < 1.0f) {
SDL_SetTextureAlphaMod(blocksTex, static_cast<Uint8>(std::clamp(clearAlpha, 0.0f, 1.0f) * 255.0f));
rwrap->setTextureAlphaMod(blocksTex, static_cast<Uint8>(std::clamp(clearAlpha, 0.0f, 1.0f) * 255.0f));
}
drawBlockTexture(renderer, blocksTex, bx, by, finalBlockSize * clearScale, v - 1);
if (blocksTex && clearAlpha < 1.0f) {
SDL_SetTextureAlphaMod(blocksTex, 255);
rwrap->setTextureAlphaMod(blocksTex, 255);
}
}
}
@ -1223,7 +1224,7 @@ void GameRenderer::renderPlayingState(
s.y += s.vy * sparkDeltaMs;
float lifeRatio = std::clamp(static_cast<float>(s.lifeMs / s.maxLifeMs), 0.0f, 1.0f);
Uint8 alpha = static_cast<Uint8>(lifeRatio * 200.0f);
SDL_SetRenderDrawColor(renderer, s.color.r, s.color.g, s.color.b, alpha);
rwrap->setDrawColor(SDL_Color{s.color.r, s.color.g, s.color.b, alpha});
float size = s.size * (0.7f + (1.0f - lifeRatio) * 0.8f);
SDL_FRect shardRect{
s.x - size * 0.5f,
@ -1231,7 +1232,7 @@ void GameRenderer::renderPlayingState(
size,
size * 1.4f
};
SDL_RenderFillRect(renderer, &shardRect);
rwrap->fillRectF(&shardRect);
++shardIt;
}
@ -1252,14 +1253,14 @@ void GameRenderer::renderPlayingState(
SDL_Color c = b.color;
Uint8 a = static_cast<Uint8>(alpha * 220.0f);
SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, a);
rwrap->setDrawColor(SDL_Color{c.r, c.g, c.b, a});
SDL_FRect outer{
b.x - radius + jitter,
b.y - radius + jitter,
radius * 2.0f,
radius * 2.0f
};
SDL_RenderRect(renderer, &outer);
rwrap->drawRectF(&outer);
SDL_FRect inner{
b.x - (radius - thickness),
@ -1267,8 +1268,8 @@ void GameRenderer::renderPlayingState(
(radius - thickness) * 2.0f,
(radius - thickness) * 2.0f
};
SDL_SetRenderDrawColor(renderer, 255, 255, 255, static_cast<Uint8>(a * 0.9f));
SDL_RenderRect(renderer, &inner);
rwrap->setDrawColor(SDL_Color{255, 255, 255, static_cast<Uint8>(a * 0.9f)});
rwrap->drawRectF(&inner);
++it;
}
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
@ -1289,14 +1290,14 @@ void GameRenderer::renderPlayingState(
}
float lifeRatio = spark.lifeMs / spark.maxLifeMs;
Uint8 alpha = static_cast<Uint8>(std::clamp(lifeRatio, 0.0f, 1.0f) * 160.0f);
SDL_SetRenderDrawColor(renderer, spark.color.r, spark.color.g, spark.color.b, alpha);
rwrap->setDrawColor(SDL_Color{spark.color.r, spark.color.g, spark.color.b, alpha});
SDL_FRect sparkRect{
spark.x - spark.size * 0.5f,
spark.y - spark.size * 0.5f,
spark.size,
spark.size * 1.4f
};
SDL_RenderFillRect(renderer, &sparkRect);
rwrap->fillRectF(&sparkRect);
++it;
}
}
@ -1540,9 +1541,9 @@ void GameRenderer::renderPlayingState(
float barW = numbersW;
float barY = numbersY + numbersH + 8.0f;
SDL_SetRenderDrawColor(renderer, 24, 80, 120, 220);
rwrap->setDrawColor(SDL_Color{24, 80, 120, 220});
SDL_FRect track{barX, barY, barW, barHeight};
SDL_RenderFillRect(renderer, &track);
rwrap->fillRectF(&track);
// Fill color brightness based on usage and highlight for top piece
float strength = (totalBlocks > 0) ? (float(blockCounts[i]) / float(totalBlocks)) : 0.0f;
@ -1556,9 +1557,9 @@ void GameRenderer::renderPlayingState(
};
float fillW = barW * std::clamp(strength, 0.0f, 1.0f);
SDL_SetRenderDrawColor(renderer, fillC.r, fillC.g, fillC.b, fillC.a);
rwrap->setDrawColor(SDL_Color{fillC.r, fillC.g, fillC.b, fillC.a});
SDL_FRect fill{barX, barY, fillW, barHeight};
SDL_RenderFillRect(renderer, &fill);
rwrap->fillRectF(&fill);
// Advance cursor to next row: after bar + gap (leave more space between blocks)
yCursor = barY + barHeight + rowGap + 6.0f;
@ -1733,10 +1734,10 @@ void GameRenderer::renderPlayingState(
SDL_FRect statsBg{statsPanelLeft, statsPanelTop, statsPanelWidth, statsPanelHeight};
if (scorePanelTex) {
SDL_RenderTexture(renderer, scorePanelTex, nullptr, &statsBg);
rwrap->renderTexture(scorePanelTex, nullptr, &statsBg);
} else {
SDL_SetRenderDrawColor(renderer, 12, 18, 32, 205);
SDL_RenderFillRect(renderer, &statsBg);
rwrap->setDrawColor(SDL_Color{12, 18, 32, 205});
rwrap->fillRectF(&statsBg);
}
scorePanelMetricsValid = true;
@ -1824,12 +1825,12 @@ void GameRenderer::renderPlayingState(
SDL_FRect panelDst{panelX, panelY, panelW, panelH};
SDL_SetTextureBlendMode(holdPanelTex, SDL_BLENDMODE_BLEND);
SDL_SetTextureScaleMode(holdPanelTex, SDL_SCALEMODE_LINEAR);
SDL_RenderTexture(renderer, holdPanelTex, nullptr, &panelDst);
rwrap->renderTexture(holdPanelTex, nullptr, &panelDst);
} else {
// fallback: draw a dark panel rect so UI is visible even without texture
SDL_SetRenderDrawColor(renderer, 12, 18, 32, 220);
rwrap->setDrawColor(SDL_Color{12, 18, 32, 220});
SDL_FRect panelDst{panelX, panelY, panelW, panelH};
SDL_RenderFillRect(renderer, &panelDst);
rwrap->fillRectF(&panelDst);
}
// Display "HOLD" label on right side
@ -1868,6 +1869,8 @@ void GameRenderer::renderCoopPlayingState(
) {
if (!renderer || !game || !pixelFont) return;
auto rwrap = renderer::MakeSDLRenderer(renderer);
static SyncLineRenderer s_syncLine;
static bool s_lastHadCompletedLines = false;
@ -1906,9 +1909,9 @@ void GameRenderer::renderCoopPlayingState(
float contentOffsetY = (winH - contentH) * 0.5f / contentScale;
auto drawRectWithOffset = [&](float x, float y, float w, float h, SDL_Color c) {
SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, c.a);
rwrap->setDrawColor(c);
SDL_FRect fr{x + contentOffsetX, y + contentOffsetY, w, h};
SDL_RenderFillRect(renderer, &fr);
rwrap->fillRectF(&fr);
};
static constexpr float COOP_GAP_PX = 20.0f;
@ -1981,19 +1984,19 @@ void GameRenderer::renderCoopPlayingState(
};
// Grid lines (draw per-half so the gap is clean)
SDL_SetRenderDrawColor(renderer, 40, 45, 60, 255);
rwrap->setDrawColor(SDL_Color{40, 45, 60, 255});
for (int x = 1; x < 10; ++x) {
float lineX = gridX + x * finalBlockSize;
SDL_RenderLine(renderer, lineX, gridY, lineX, gridY + GRID_H);
rwrap->renderLine(lineX, gridY, lineX, gridY + GRID_H);
}
for (int x = 1; x < 10; ++x) {
float lineX = gridX + HALF_W + COOP_GAP_PX + x * finalBlockSize;
SDL_RenderLine(renderer, lineX, gridY, lineX, gridY + GRID_H);
rwrap->renderLine(lineX, gridY, lineX, gridY + GRID_H);
}
for (int y = 1; y < CoopGame::ROWS; ++y) {
float lineY = gridY + y * finalBlockSize;
SDL_RenderLine(renderer, gridX, lineY, gridX + HALF_W, lineY);
SDL_RenderLine(renderer, gridX + HALF_W + COOP_GAP_PX, lineY, gridX + HALF_W + COOP_GAP_PX + HALF_W, lineY);
rwrap->renderLine(gridX, lineY, gridX + HALF_W, lineY);
rwrap->renderLine(gridX + HALF_W + COOP_GAP_PX, lineY, gridX + HALF_W + COOP_GAP_PX + HALF_W, lineY);
}
// In-grid 3D starfield + ambient sparkles (match classic feel, per-half)
@ -2178,10 +2181,10 @@ void GameRenderer::renderCoopPlayingState(
float pulse = 0.5f + 0.5f * std::sin(sp.pulse);
Uint8 alpha = static_cast<Uint8>(std::clamp(lifeRatio * pulse, 0.0f, 1.0f) * 255.0f);
SDL_SetRenderDrawColor(renderer, sp.color.r, sp.color.g, sp.color.b, alpha);
rwrap->setDrawColor(SDL_Color{sp.color.r, sp.color.g, sp.color.b, alpha});
float half = sp.size * 0.5f;
SDL_FRect fr{ originX + sp.x - half, gridY + sp.y - half, sp.size, sp.size };
SDL_RenderFillRect(renderer, &fr);
rwrap->fillRectF(&fr);
++it;
}
}
@ -2200,14 +2203,14 @@ void GameRenderer::renderCoopPlayingState(
}
float lifeRatio = spark.lifeMs / spark.maxLifeMs;
Uint8 alpha = static_cast<Uint8>(std::clamp(lifeRatio, 0.0f, 1.0f) * 160.0f);
SDL_SetRenderDrawColor(renderer, spark.color.r, spark.color.g, spark.color.b, alpha);
rwrap->setDrawColor(SDL_Color{spark.color.r, spark.color.g, spark.color.b, alpha});
SDL_FRect sparkRect{
spark.x - spark.size * 0.5f,
spark.y - spark.size * 0.5f,
spark.size,
spark.size * 1.4f
};
SDL_RenderFillRect(renderer, &sparkRect);
rwrap->fillRectF(&sparkRect);
++it;
}
}
@ -2239,17 +2242,17 @@ void GameRenderer::renderCoopPlayingState(
}
if (rs.leftFull && rs.rightFull) {
SDL_SetRenderDrawColor(renderer, 140, 210, 255, 45);
rwrap->setDrawColor(SDL_Color{140, 210, 255, 45});
SDL_FRect frL{gridX, rowY, HALF_W, finalBlockSize};
SDL_RenderFillRect(renderer, &frL);
rwrap->fillRectF(&frL);
SDL_FRect frR{gridX + HALF_W + COOP_GAP_PX, rowY, HALF_W, finalBlockSize};
SDL_RenderFillRect(renderer, &frR);
rwrap->fillRectF(&frR);
} else if (rs.leftFull ^ rs.rightFull) {
SDL_SetRenderDrawColor(renderer, 90, 140, 220, 35);
rwrap->setDrawColor(SDL_Color{90, 140, 220, 35});
float w = HALF_W;
float x = rs.leftFull ? gridX : (gridX + HALF_W + COOP_GAP_PX);
SDL_FRect fr{x, rowY, w, finalBlockSize};
SDL_RenderFillRect(renderer, &fr);
rwrap->fillRectF(&fr);
}
}
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
@ -2446,7 +2449,7 @@ void GameRenderer::renderCoopPlayingState(
float elapsed = static_cast<float>(nowTicks - sf.startTick);
float t = sf.durationMs <= 0.0f ? 1.0f : std::clamp(elapsed / sf.durationMs, 0.0f, 1.0f);
Uint8 alpha = static_cast<Uint8>(std::lround(255.0f * t));
if (blocksTex) SDL_SetTextureAlphaMod(blocksTex, alpha);
if (blocksTex) rwrap->setTextureAlphaMod(blocksTex, alpha);
int minCy = 4;
int maxCy = -1;
@ -2493,7 +2496,7 @@ void GameRenderer::renderCoopPlayingState(
drawBlockTexturePublic(renderer, blocksTex, px, py, sf.tileSize, livePiece.type);
}
}
if (blocksTex) SDL_SetTextureAlphaMod(blocksTex, 255);
if (blocksTex) rwrap->setTextureAlphaMod(blocksTex, 255);
// End fade after duration, but never stop while we are pinning (otherwise
// I can briefly disappear until it becomes visible in the real grid).
@ -2513,12 +2516,12 @@ void GameRenderer::renderCoopPlayingState(
float py = gridY + (float)pyIdx * finalBlockSize + offsets.second;
if (isGhost) {
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(renderer, 180, 180, 180, 20);
rwrap->setDrawColor(SDL_Color{180, 180, 180, 20});
SDL_FRect rect = {px + 2.0f, py + 2.0f, finalBlockSize - 4.0f, finalBlockSize - 4.0f};
SDL_RenderFillRect(renderer, &rect);
SDL_SetRenderDrawColor(renderer, 180, 180, 180, 30);
rwrap->fillRectF(&rect);
rwrap->setDrawColor(SDL_Color{180, 180, 180, 30});
SDL_FRect border = {px + 1.0f, py + 1.0f, finalBlockSize - 2.0f, finalBlockSize - 2.0f};
SDL_RenderRect(renderer, &border);
rwrap->drawRectF(&border);
} else {
drawBlockTexturePublic(renderer, blocksTex, px, py, finalBlockSize, p.type);
}
@ -2593,7 +2596,7 @@ void GameRenderer::renderCoopPlayingState(
auto drawNextPanel = [&](float panelX, float panelY, const CoopGame::Piece& piece) {
SDL_FRect panel{ panelX, panelY, nextPanelW, nextPanelH };
if (nextPanelTex) {
SDL_RenderTexture(renderer, nextPanelTex, nullptr, &panel);
rwrap->renderTexture(nextPanelTex, nullptr, &panel);
} else {
drawRectWithOffset(panel.x - contentOffsetX, panel.y - contentOffsetY, panel.w, panel.h, SDL_Color{18,22,30,200});
}
@ -2721,10 +2724,10 @@ void GameRenderer::renderCoopPlayingState(
float panelX = (side == CoopGame::PlayerSide::Right) ? (columnRightX - panelW) : columnLeftX;
SDL_FRect panelBg{ panelX, panelY, panelW, panelH };
if (scorePanelTex) {
SDL_RenderTexture(renderer, scorePanelTex, nullptr, &panelBg);
rwrap->renderTexture(scorePanelTex, nullptr, &panelBg);
} else {
SDL_SetRenderDrawColor(renderer, 12, 18, 32, 205);
SDL_RenderFillRect(renderer, &panelBg);
rwrap->setDrawColor(SDL_Color{12, 18, 32, 205});
rwrap->fillRectF(&panelBg);
}
float textDrawX = panelX + statsPanelPadLeft;
@ -2791,9 +2794,10 @@ void GameRenderer::renderExitPopup(
SDL_SetRenderViewport(renderer, nullptr);
SDL_SetRenderScale(renderer, 1.0f, 1.0f);
SDL_SetRenderDrawColor(renderer, 2, 4, 12, 210);
auto rwrap = renderer::MakeSDLRenderer(renderer);
rwrap->setDrawColor(SDL_Color{2, 4, 12, 210});
SDL_FRect fullWin{0.0f, 0.0f, winW, winH};
SDL_RenderFillRect(renderer, &fullWin);
rwrap->fillRectF(&fullWin);
const float scale = std::max(0.8f, logicalScale);
const float panelW = 740.0f * scale;
@ -2811,8 +2815,8 @@ void GameRenderer::renderExitPopup(
panel.w + 4.0f * scale,
panel.h + 4.0f * scale
};
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 140);
SDL_RenderFillRect(renderer, &shadow);
rwrap->setDrawColor(SDL_Color{0, 0, 0, 140});
rwrap->fillRectF(&shadow);
const std::array<SDL_Color, 3> panelLayers{
SDL_Color{7, 10, 22, 255},
@ -2828,12 +2832,12 @@ void GameRenderer::renderExitPopup(
panel.h - inset * 2.0f
};
SDL_Color c = panelLayers[i];
SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, c.a);
SDL_RenderFillRect(renderer, &layer);
rwrap->setDrawColor(c);
rwrap->fillRectF(&layer);
}
SDL_SetRenderDrawColor(renderer, 60, 90, 150, 255);
SDL_RenderRect(renderer, &panel);
rwrap->setDrawColor(SDL_Color{60, 90, 150, 255});
rwrap->drawRectF(&panel);
SDL_FRect insetFrame{
panel.x + 10.0f * scale,
@ -2841,8 +2845,8 @@ void GameRenderer::renderExitPopup(
panel.w - 20.0f * scale,
panel.h - 20.0f * scale
};
SDL_SetRenderDrawColor(renderer, 24, 45, 84, 255);
SDL_RenderRect(renderer, &insetFrame);
rwrap->setDrawColor(SDL_Color{24, 45, 84, 255});
rwrap->drawRectF(&insetFrame);
const float contentPad = 44.0f * scale;
float textX = panel.x + contentPad;
@ -2856,9 +2860,9 @@ void GameRenderer::renderExitPopup(
pixelFont->draw(renderer, textX, cursorY, title, titleScale, SDL_Color{255, 224, 130, 255});
cursorY += titleH + 18.0f * scale;
SDL_SetRenderDrawColor(renderer, 32, 64, 110, 210);
rwrap->setDrawColor(SDL_Color{32, 64, 110, 210});
SDL_FRect divider{textX, cursorY, contentWidth, 2.0f * scale};
SDL_RenderFillRect(renderer, &divider);
rwrap->fillRectF(&divider);
cursorY += 26.0f * scale;
const std::array<const char*, 2> lines{
@ -2899,29 +2903,29 @@ void GameRenderer::renderExitPopup(
SDL_Color border = selected ? SDL_Color{255, 225, 150, 255} : SDL_Color{90, 120, 170, 255};
SDL_Color topEdge = SDL_Color{Uint8(std::min(255, body.r + 20)), Uint8(std::min(255, body.g + 20)), Uint8(std::min(255, body.b + 20)), 255};
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 110);
rwrap->setDrawColor(SDL_Color{0, 0, 0, 110});
SDL_FRect btnShadow{btn.x + 6.0f * scale, btn.y + 8.0f * scale, btn.w, btn.h};
SDL_RenderFillRect(renderer, &btnShadow);
rwrap->fillRectF(&btnShadow);
SDL_SetRenderDrawColor(renderer, body.r, body.g, body.b, body.a);
SDL_RenderFillRect(renderer, &btn);
rwrap->setDrawColor(body);
rwrap->fillRectF(&btn);
SDL_FRect topStrip{btn.x, btn.y, btn.w, 6.0f * scale};
SDL_SetRenderDrawColor(renderer, topEdge.r, topEdge.g, topEdge.b, topEdge.a);
SDL_RenderFillRect(renderer, &topStrip);
rwrap->setDrawColor(topEdge);
rwrap->fillRectF(&topStrip);
SDL_SetRenderDrawColor(renderer, border.r, border.g, border.b, border.a);
SDL_RenderRect(renderer, &btn);
rwrap->setDrawColor(border);
rwrap->drawRectF(&btn);
if (selected) {
SDL_SetRenderDrawColor(renderer, 255, 230, 160, 90);
rwrap->setDrawColor(SDL_Color{255, 230, 160, 90});
SDL_FRect glow{
btn.x - 6.0f * scale,
btn.y - 6.0f * scale,
btn.w + 12.0f * scale,
btn.h + 12.0f * scale
};
SDL_RenderRect(renderer, &glow);
rwrap->drawRectF(&glow);
}
const float labelScale = 1.35f * scale;
@ -2962,9 +2966,10 @@ void GameRenderer::renderPauseOverlay(
SDL_SetRenderScale(renderer, 1.0f, 1.0f);
// Draw full screen overlay (darken)
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 180);
auto rwrap = renderer::MakeSDLRenderer(renderer);
rwrap->setDrawColor(SDL_Color{0, 0, 0, 180});
SDL_FRect pauseOverlay{0, 0, winW, winH};
SDL_RenderFillRect(renderer, &pauseOverlay);
rwrap->fillRectF(&pauseOverlay);
// Draw centered text
const char* pausedText = "PAUSED";