From 80a26222676bbe536128ab6a94661d28c282f64f Mon Sep 17 00:00:00 2001 From: mlangkabel Date: Mon, 13 Jul 2026 21:31:52 +0200 Subject: [PATCH] Redefine camera scroll as view center --- src/ui/GameWorldView.cpp | 24 ++++++++++++++++-------- src/ui/GameWorldView.h | 4 ++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/ui/GameWorldView.cpp b/src/ui/GameWorldView.cpp index d681bad..62edce3 100644 --- a/src/ui/GameWorldView.cpp +++ b/src/ui/GameWorldView.cpp @@ -293,7 +293,7 @@ void GameWorldView::onFrame() // Apply held scroll { // Pan speed depends on where the view is centered (REQ-UI-SCROLL-SPEED). - const float viewCenterX = m_scrollXTiles + viewportWidthTiles() / 2.0f; + const float viewCenterX = m_scrollXTiles; const float delta = panSpeedTilesPerSecondAt(viewCenterX) * static_cast(elapsed) / 1000.0f; const float scrollBefore = m_scrollXTiles; @@ -435,10 +435,15 @@ float GameWorldView::viewportWidthTiles() const return static_cast(width()) / tilePx(); } +float GameWorldView::viewLeftTiles() const +{ + return m_scrollXTiles - viewportWidthTiles() / 2.0f; +} + QPointF GameWorldView::worldToWidget(QVector2D worldPos) const { return QPointF( - static_cast((worldPos.x() - m_scrollXTiles) * tilePx()), + static_cast((worldPos.x() - viewLeftTiles()) * tilePx()), static_cast(worldPos.y() * tilePx())); } @@ -450,14 +455,14 @@ QPointF GameWorldView::tileToWidget(QPoint tile) const QPoint GameWorldView::widgetToTile(QPoint widgetPt) const { - const float wx = static_cast(widgetPt.x()) / tilePx() + m_scrollXTiles; + const float wx = static_cast(widgetPt.x()) / tilePx() + viewLeftTiles(); const float wy = static_cast(widgetPt.y()) / tilePx(); return QPoint(static_cast(std::floor(wx)), static_cast(std::floor(wy))); } QVector2D GameWorldView::widgetToWorld(QPoint widgetPt) const { - const float wx = static_cast(widgetPt.x()) / tilePx() + m_scrollXTiles; + const float wx = static_cast(widgetPt.x()) / tilePx() + viewLeftTiles(); const float wy = static_cast(widgetPt.y()) / tilePx(); return QVector2D(wx, wy); } @@ -471,9 +476,9 @@ QRectF GameWorldView::tileRect(QPoint tile) const QRect GameWorldView::viewportRect() const { - const int left = static_cast(std::floor(m_scrollXTiles)) - 1; + const int left = static_cast(std::floor(viewLeftTiles())) - 1; const int top = 0; - const int right = static_cast(std::ceil(m_scrollXTiles + viewportWidthTiles())) + 1; + const int right = static_cast(std::ceil(viewLeftTiles() + viewportWidthTiles())) + 1; const int bottom = m_config->world.heightTiles; return QRect(left, top, right - left, bottom - top); } @@ -546,8 +551,11 @@ float GameWorldView::panSpeedTilesPerSecondAt(float viewCenterXTiles) const void GameWorldView::clampScroll() { + // m_scrollXTiles is the view center, so the pan limits are the edges themselves: + // the view can pan left until the buildable/asteroid edge is centered, and right + // until the enemy stations are centered (revealing a little space beyond them). const float leftBound = asteroidLeftEdge(); - const float rightBound = enemyStationRightEdge() - viewportWidthTiles(); + const float rightBound = enemyStationRightEdge(); m_scrollXTiles = std::max(leftBound, std::min(m_scrollXTiles, rightBound)); } @@ -906,7 +914,7 @@ void GameWorldView::drawPortGlyph(QPainter& painter, QPoint bodyTile, void GameWorldView::drawTiles(QPainter& painter) { - const int leftTile = static_cast(std::floor(m_scrollXTiles)) - 1; + const int leftTile = static_cast(std::floor(viewLeftTiles())) - 1; const int rightTile = leftTile + static_cast(std::ceil(viewportWidthTiles())) + 2; const int bottomTile = m_config->world.heightTiles; diff --git a/src/ui/GameWorldView.h b/src/ui/GameWorldView.h index ead933c..1c89fbe 100644 --- a/src/ui/GameWorldView.h +++ b/src/ui/GameWorldView.h @@ -134,6 +134,9 @@ private: float tilePx() const; float viewportWidthTiles() const; + // World-X (tiles) at the left edge of the viewport. m_scrollXTiles stores the + // view center; this derives the left edge the world<->widget conversions need. + float viewLeftTiles() const; QPointF worldToWidget(QVector2D worldPos) const; QPointF tileToWidget(QPoint tile) const; QPoint widgetToTile(QPoint widgetPt) const; @@ -218,6 +221,7 @@ private: std::mt19937 m_rng; double m_gameSpeedMultiplier; double m_prevNonZeroSpeed; + // World-X (tiles) at the center of the viewport (see viewLeftTiles()). float m_scrollXTiles; QTimer* m_renderTimer;