game.cam.camrig — the tactical camera's maths.
One orbit station: a target point on the board, a yaw, a pitch and a
distance. Everything else here turns that into a world pose, keeps it
inside limits the portrait frame can actually hold, and eases it.
THE SCREEN IS 1080x1440. Horizontal room is the scarce resource, so the
distance floor is derived from how wide the board projects at the
current yaw rather than being a constant: swung side-on the board is 20
units across instead of 16, and a fixed distance would push its edges
off the sides of a tall frame. `fitDistance` is that derivation, and it
is what makes the board legible at EVERY angle rather than only the one
it was composed at.
setRoom(bounds: any, inset: number?) → void
--!desc Read the room the camera may stand in from a world-space bounds
--! table, inset so the lens never grazes a pier.
--!arg bounds A bounds table with `min` and `max` (what `hierarchyBounds`
--! returns).
--!arg inset How far inside the walls to stay (default 3.5).
--!example CamRig.setRoom(entity.find("Greenhouse"):hierarchyBounds())
| arg | type | description |
|---|
| bounds | any | |
| inset | number? | |
rad(d: number) → number
| arg | type | description |
|---|
| d | number | |
forward(yawDeg: number, pitchDeg: number) → void
--!desc The camera's unit forward vector for a yaw/pitch station.
--!arg yawDeg Yaw in degrees, about +Y.
--!arg pitchDeg Pitch in degrees; negative looks down.
--!return Three numbers: fx, fy, fz.
--!example local fx, fy, fz = CamRig.forward(196, -47)
| arg | type | description |
|---|
| yawDeg | number | |
| pitchDeg | number | |
quat(yawDeg: number, pitchDeg: number) → void
--!desc The rotation quaternion for a yaw/pitch station.
--!arg yawDeg Yaw in degrees.
--!arg pitchDeg Pitch in degrees.
--!return A {x, y, z, w} table.
--!example ent.rotation = CamRig.quat(196, -47)
| arg | type | description |
|---|
| yawDeg | number | |
| pitchDeg | number | |
rightXZ(yawDeg: number) → void
--!desc Screen-right in the XZ plane for a yaw — the axis the board's
--! width is measured along when working out whether it fits.
--!arg yawDeg Yaw in degrees.
--!return Two numbers: rx, rz.
--!example local rx, rz = CamRig.rightXZ(90)
| arg | type | description |
|---|
| yawDeg | number | |
projHalfWidth(yawDeg: number) → number
--!desc The closest the camera may stand at this yaw and still hold the
--! whole board inside a 1080x1440 frame. The board is 8 wide and 10
--! deep, so its projected width changes as the camera swings.
--!arg yawDeg Yaw in degrees.
--!arg fovDeg Vertical field of view in degrees.
--!return The minimum distance in world units.
--!example local d = CamRig.fitDistance(90, 55)
--!desc Half the board's width measured across the screen at a yaw —
--! 8 tiles wide and 10 deep, so it changes by a quarter as the camera
--! swings.
--!arg yawDeg Yaw in degrees.
--!return The half-width in world units.
--!example local w = CamRig.projHalfWidth(90)
| arg | type | description |
|---|
| yawDeg | number | |
fitDistance(yawDeg: number, fovDeg: number) → number
| arg | type | description |
|---|
| yawDeg | number | |
| fovDeg | number | |
newState( ) → any
--!desc A fresh orbit station sitting at HOME, with its eased copy in
--! step so the first frame does not slide.
--!return A station table: want/have yaw, pitch, dist, target and fov.
--!example local s = CamRig.newState()
insideRoom(s: any, yawDeg: number, pitchDeg: number, dist: number) → boolean
--!desc Hold a station inside the limits the frame can carry: pitch
--! between overhead and near-level, distance no closer than the fit.
--!arg s A station table, edited in place.
--!return The same station.
--!example CamRig.clamp(s)
--!desc Whether the camera would still be inside the room at this
--! station.
--!arg s A station table.
--!arg yawDeg The yaw to test.
--!arg pitchDeg The pitch to test.
--!arg dist The distance to test.
--!return true when the camera stands inside CamRig.ROOM.
--!example if CamRig.insideRoom(s, 90, -47, 34) then ... end
| arg | type | description |
|---|
| s | any | |
| yawDeg | number | |
| pitchDeg | number | |
| dist | number | |
distFor(yaw: number, pitch: number) → number
The distance is derived, so the frame holds through a swing.
| arg | type | description |
|---|
| yaw | number | |
| pitch | number | |
toward(cur: number, want: number, k: number, dt: number) → number
| arg | type | description |
|---|
| cur | number | |
| want | number | |
| k | number | |
| dt | number | |
ease(s: any, dt: number, rate: number?) → void
--!desc Ease the station's live values toward what was asked for. Pure
--! cosmetic motion: it changes no game state, so it is legal in a game
--! with no clock.
--!arg s A station table, edited in place.
--!arg dt Seconds since the last frame.
--!arg rate Optional stiffness (default 12).
--!example CamRig.ease(s, dt)
| arg | type | description |
|---|
| s | any | |
| dt | number | |
| rate | number? | |
snap(s: any) → void
--!desc Snap the eased values onto what was asked for — used when the
--! camera is placed rather than moved (a cut, a scene load).
--!arg s A station table, edited in place.
--!example CamRig.snap(s)
eye(s: any) → void
--!desc The world position the camera stands at for a station's eased
--! values.
--!arg s A station table.
--!return A {x, y, z} table.
--!example ent.position = CamRig.eye(s)
apply(s: any, camEnt: any) → boolean
--!desc Write a station onto a camera entity: position, rotation and,
--! when the entity carries a Camera component, its field of view.
--!arg s A station table.
--!arg camEnt The camera entity proxy.
--!return true when the pose was written.
--!example CamRig.apply(s, entity(camera.main()))
| arg | type | description |
|---|
| s | any | |
| camEnt | any | |
focusTile(s: any, x: number, y: number, strength: number?) → void
--!desc Aim the station at a board tile, keeping the deliberate drop
--! below the board that lifts it into the middle of the tall frame.
--!arg s A station table, edited in place.
--!arg x Tile column.
--!arg y Tile row.
--!arg strength How far to move toward it, 0..1 (default 0.55 — a lean,
--! not a snap, so the player never loses where they were).
--!example CamRig.focusTile(s, 4, 7)
| arg | type | description |
|---|
| s | any | |
| x | number | |
| y | number | |
| strength | number? | |