Add paused-state vignette border to game world view

Draw a black gradient border (50% alpha at the viewport edges fading to
transparent toward the center) while the game is paused (speed 0x), making
the paused state hard to miss.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7N59FsLA5e2kuVdqe4Uhc
This commit is contained in:
2026-07-19 21:21:26 +02:00
parent d4a9d91c5d
commit 91995c57ee
2 changed files with 45 additions and 0 deletions

View File

@@ -431,6 +431,7 @@ void GameWorldView::paintGL()
drawBeams(painter); drawBeams(painter);
drawOverlays(painter); drawOverlays(painter);
drawScreenSpace(painter); drawScreenSpace(painter);
drawPauseBorder(painter);
drawReplayOverlay(painter); drawReplayOverlay(painter);
} }
@@ -1695,6 +1696,46 @@ void GameWorldView::drawScreenSpace(QPainter& /*painter*/)
{ {
} }
void GameWorldView::drawPauseBorder(QPainter& painter)
{
if (m_gameSpeedMultiplier > 0.0) { return; }
// Border thickness in pixels, capped so it never exceeds half the viewport on
// very small windows (which would leave no un-darkened center).
const qreal borderPx = std::min<qreal>(
100.0, std::min(width(), height()) / 2.0);
if (borderPx <= 0.0) { return; }
const QColor edge(0, 0, 0, 128); // 50% black at the viewport edge
const QColor inner(0, 0, 0, 0); // fully transparent toward the center
painter.save();
// Each side is a linear gradient fading from `edge` at the viewport border to
// `inner` toward the center. Corners overlap and read as a natural vignette.
QLinearGradient left(0, 0, borderPx, 0);
left.setColorAt(0.0, edge);
left.setColorAt(1.0, inner);
painter.fillRect(QRectF(0, 0, borderPx, height()), left);
QLinearGradient right(width(), 0, width() - borderPx, 0);
right.setColorAt(0.0, edge);
right.setColorAt(1.0, inner);
painter.fillRect(QRectF(width() - borderPx, 0, borderPx, height()), right);
QLinearGradient top(0, 0, 0, borderPx);
top.setColorAt(0.0, edge);
top.setColorAt(1.0, inner);
painter.fillRect(QRectF(0, 0, width(), borderPx), top);
QLinearGradient bottom(0, height(), 0, height() - borderPx);
bottom.setColorAt(0.0, edge);
bottom.setColorAt(1.0, inner);
painter.fillRect(QRectF(0, height() - borderPx, width(), borderPx), bottom);
painter.restore();
}
void GameWorldView::drawReplayOverlay(QPainter& painter) void GameWorldView::drawReplayOverlay(QPainter& painter)
{ {
if (!m_replayPlayer) { return; } if (!m_replayPlayer) { return; }

View File

@@ -131,6 +131,10 @@ private:
void drawBeams(QPainter& painter); void drawBeams(QPainter& painter);
void drawOverlays(QPainter& painter); void drawOverlays(QPainter& painter);
void drawScreenSpace(QPainter& painter); void drawScreenSpace(QPainter& painter);
// Vignette-style border shown while the game is paused (speed 0x) to make the
// paused state hard to miss: a black frame whose alpha fades from 50% at the
// viewport edges to 0% toward the center.
void drawPauseBorder(QPainter& painter);
void drawReplayOverlay(QPainter& painter); void drawReplayOverlay(QPainter& painter);
float getTilePx() const; float getTilePx() const;