Quick Design Spec: Camera
Type: New Small System Scope: The one gameplay camera: locked-zoom top-down follow. Does NOT own: UI layout (UI/HUD), tide-tint rendering (shader contract), or any cinematic/cutscene system (none exists, deliberately). Date: 2026-08-27 Estimated Implementation: ~1 day
Overview
One camera, one job: keep your hero centered-ish and the world readable. Fixed top-down, locked zoom, gentle follow. The camera is deliberately inert — it is the anti-pillar made hardware ("NOT an RTS: you never command from a detached view; you are always your hero"). Nothing in the game moves the camera off the player, and nothing shakes it.
Core Rules
- Locked zoom, integer-scaled. Orthographic, zoom fixed at **64 px per world unit** at 1080p (exactly 2× the 32 PPU with point filtering — crisp pixels by construction, no shimmer). This is the "gameplay zoom" every art-bible silhouette test (§5.4's 64–96 px band, §8.A tiers) is calibrated against; changing it invalidates those tests, so it is a rule, not a knob. Other resolutions scale by the nearest integer multiple that preserves ≥ the §8.A readability tier.
- Follow: smoothed centering with slight aim bias. The camera tracks the owner's player at
followSmoothTime, offset toward the aim vector byaimBiasFracof the screen (see the read ahead of you — the direction you're aiming into gets more screen). Bias applies identically on both input schemes (the shared aim vector, movement Rule 3). - The camera never detaches. No free-look, no map pan, no spectate-the-base view, no cutscene takeovers (anti-pillar: always your hero). The only non-follow motions are the instant snaps that ride existing authority events (tide deposit, death respawn) — the camera arrives with the body, one hard cut, no travel pan (a pan would dramatize what the tone rule states as a world fact).
- No screen shake, no zoom punch (MVP). Impact weight is delivered by sprite treatment (squash-stretch, hit-stop are combat/art decisions) — never camera motion. A future shake proposal is an art-bible + accessibility conversation, not a camera tune.
- Downed/dead: camera stays on your body until respawn snaps home (combat's flow). No corpse-cam drift, no auto-switch to teammates — you watch from where you fell (the helpless wait is combat Open Question 5's territory; the camera doesn't edit it).
Tuning Knobs
| Knob | Default | Range | Category | Rationale |
|---|---|---|---|---|
followSmoothTime | 0.12 s | 0.05–0.25 | feel | Tight enough that dashes never outrun the frame; loose enough to not jitter |
aimBiasFrac | 0.10 | 0–0.20 | feel | Screen-fraction lead toward aim; 0 disables; >0.2 makes the character ride screen edges |
Values live in assets/data/camera.json. Zoom is deliberately not a knob (Rule 1).
**Implementation addenda (2026-09-08, core-camera epic — recorded here so the design doc carries what the code enforces):**
- Hard bounds vs. safe ranges. The ranges above are safe ranges: a value outside them loads with a stage-9 warning (ADR-0006 convention). Two values are impossible and reject the file with an error:
followSmoothTime ≤ 0(the smoothing divides by it) and|aimBiasFrac| > 0.5(past half the visible height the bias point is off-screen; symmetric, inclusive at ±0.5). Non-finite numbers (NaN,±Infinity) are rejected by the reader as wrong-type. - **"aimBiasFrac of the screen" = fraction of the visible height in world units** (
2 × orthographicSize, 16.875 u at 1080p) — the axis Rule 1 fixes; width varies with aspect. At the default 0.10 the lead is 1.6875 u at 1080p and scales with Rule 1's integer zoom (2.25 u at 720p). - Hard cuts (Rule 3) ride
ISnapSource.Snapped(SnapReason, pos)with the closed listTideDeposit | DeathRespawn— TR-move-005's snap list minus the BB EC21 correction, which is an interpolated write, not a cut. The camera state is written once (position = snap point, velocity zero) and the follow resumes toward the body, which the emitter has already moved to the same point.
Acceptance Criteria
- [ ] [UNIT] World-to-screen scale is exactly 64 px/u at 1080p and an integer multiple of 32 at every supported resolution (Rule 1 — testable as pure math).
- [ ] [UNIT] Schema-negative: no free-look, pan, spectate, or cutscene camera state exists anywhere.
- [ ] [INTEGRATION] A full-speed dash (22 u/s × 0.14 s) never exits the safe frame — the player remains fully on-screen throughout at default smoothing.
- [ ] [INTEGRATION] Tide deposit and death respawn produce one hard cut each — no travel pan, no easing across the world.
- [ ] [EXPERIENTIAL] Silhouette readability at gameplay zoom matches the art bible's §5.4 test on real assets (the calibration this camera exists to hold).
- [ ] Regression: aim bias behaves identically on mouse and twin-stick (one aim vector in, movement AC parity preserved).
Systems Index
Already tracked as MVP system #3 (Core, quick-spec, "parallel-buildable"). On approval: status → Designed (quick-spec).
Forward refs owned elsewhere: letterboxing/aspect policy at ultrawide → UI/HUD quick-spec; tide-tint is a shader-layer concern the camera never touches (art bible §8.B).