extract the scroll position into WorldCamera
Second seam of the GameWorldView decomposition: the view no longer owns a scroll position, only the pan intent and the bounds. WorldCamera works purely in world units — tiles and tiles per second, never pixels. That is what keeps it independent of WorldCoordinates: the two meet only where GameWorldView feeds getViewCenterXTiles() into the transform, and neither knows the other exists. Two things are passed in rather than reached for, both so the camera stays a plain value with no simulation dependency: - ScrollBounds, because the pan limits move with asteroid expansion and with pushes. The camera clamps on every advance(), not only when panning, so the view follows the bounds inward when they shrink. - PanDirection, because pan intent is not the camera's business. Today GameWorldView collapses its two held-key flags into it; if controls become rebindable the camera's interface does not change. The config structs are referenced, not copied: they live inside the Simulation's GameConfig, which is assigned in place on restart (REQ-CFG-RELOAD), so reloaded scroll tuning takes effect without rebuilding the camera. A test pins that. The pan-speed curve (REQ-UI-SCROLL-SPEED) had no coverage at all and is the least obvious code in the file — two ramps combined by min, with a peak below the fast speed where the bands overlap in a narrow contest zone, and a hard step when the band width is zero. All of that is now tested. Behaviour is unchanged, including the cases worth naming: holding both keys still cancels out, and the moved/not-moved result that drives the box-select refresh still counts movement caused purely by the bounds changing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JcReq7hVk4KUPhTDKWAG7K
This commit is contained in:
@@ -49,6 +49,7 @@
|
||||
#include "TickDriver.h"
|
||||
#include "TunnelCompletion.h"
|
||||
#include "VisualsConfig.h"
|
||||
#include "WorldCamera.h"
|
||||
#include "WorldCoordinates.h"
|
||||
|
||||
struct Command;
|
||||
@@ -184,9 +185,9 @@ private:
|
||||
|
||||
float getAsteroidLeftEdge() const;
|
||||
float getEnemyStationRightEdge() const;
|
||||
// Horizontal pan speed at a given view-center X, in tiles/s (REQ-UI-SCROLL-SPEED).
|
||||
float panSpeedTilesPerSecondAt(float viewCenterXTiles) const;
|
||||
void clampScroll();
|
||||
// The camera's current pan limits, read fresh from the simulation each frame:
|
||||
// both edges move with asteroid expansion and with pushes (REQ-GW-SCROLL-LIMIT).
|
||||
ScrollBounds getScrollBounds() const;
|
||||
|
||||
bool isValidPlacement(BuildingType type, QPoint anchor, Rotation rot) const;
|
||||
std::optional<BuildingId> buildingAtTile(QPoint tile) const;
|
||||
@@ -333,8 +334,9 @@ private:
|
||||
std::mt19937 m_rng;
|
||||
double m_gameSpeedMultiplier;
|
||||
double m_prevNonZeroSpeed;
|
||||
// World-X (tiles) at the center of the viewport (see getViewLeftTiles()).
|
||||
float m_scrollXTiles;
|
||||
// Horizontal view position (REQ-UI-SCROLL). Owns the scroll position itself;
|
||||
// this widget only supplies the pan intent and the simulation-derived bounds.
|
||||
WorldCamera m_camera;
|
||||
|
||||
QTimer* m_renderTimer;
|
||||
|
||||
@@ -390,6 +392,11 @@ private:
|
||||
QPoint m_boxStartTile;
|
||||
QPoint m_boxCurrentTile;
|
||||
|
||||
// Held-key state for the A / D pan controls (REQ-UI-SCROLL, REQ-UI-HOTKEYS),
|
||||
// collapsed into a PanDirection for the camera each frame. Kept here rather
|
||||
// than on the camera because it is key state, not view state: once controls
|
||||
// are rebindable this becomes an input mapper publishing the direction, and
|
||||
// the camera's interface does not change.
|
||||
bool m_scrollLeft;
|
||||
bool m_scrollRight;
|
||||
bool m_gameOverShown;
|
||||
|
||||
Reference in New Issue
Block a user