feat(camera): #78 deterministic Camera.zoom (Q16.16 render-time zoom)
The #78 investigation rejected hardware f32/f64 for the coordinate types (they would desync lockstep/replay/save) and identified camera zoom as the one genuinely-missing render feature. Ship it: Camera.zoom(scale) scales the whole view about the screen centre by a Q16.16 factor, threaded through the same two framebuffer chokepoints (rt_put_px/rt_fill_rect) that carry the camera offset, so it composes with Camera.set/follow/shake. Gated by an internal rt_cam_zoomed flag so a game that never zooms renders byte-for-byte identically (golden renders unchanged); Camera.zoom(1.0) turns it back off. The world coordinate types stay integer px + Q16.16 velocity, so it's a pure render-time transform and itself deterministic. Example examples/library/camera_zoom.ludic (pixel-readback verified), docs page, RFC updated (docs/RFC-POSITION-TYPES.md). Full suite 105/0, fixpoint holds. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
5af5bdd060
commit
6a83c28e05
8 changed files with 14932 additions and 14780 deletions
31
docs/language/camera/camera-zoom.md
Normal file
31
docs/language/camera/camera-zoom.md
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
id: camera-zoom
|
||||
name: Camera.zoom
|
||||
category: camera
|
||||
kind: namespace-method
|
||||
tokens: Camera.zoom
|
||||
sig: Camera.zoom(scale)
|
||||
tip: Scale the whole view about the screen centre by a Q16.16 factor (1.0 = none).
|
||||
order: 4
|
||||
ns: Camera
|
||||
member: zoom
|
||||
---
|
||||
|
||||
Sets a render-time zoom: every draw is scaled about the screen centre by <code>scale</code>, a Q16.16 <code>fixed</code> factor. <code>1.0</code> is no zoom (and turns the zoom path back off, restoring the byte-identical un-zoomed blit); <code>2.0</code> is 2x in; <code>0.5</code> is 2x out. It composes with <a href="camera-set"><code>Camera.set</code></a> / <a href="camera-follow"><code>Camera.follow</code></a> (which move the view) and <a href="camera-shake"><code>Camera.shake</code></a>.
|
||||
|
||||
Zoom is a *render-time transform*, not a change to the world coordinate types — those stay integer pixels + Q16.16 velocity so lockstep, replay and <code>world_save</code> hold (see the position-types RFC, #78). Because it rides on fixed-point, the zoom is itself deterministic: the same <code>scale</code> produces the same pixels on every machine and headless.
|
||||
|
||||
Parameters:
|
||||
- `scale` — the zoom factor (`fixed`); `1.0` = no zoom, `>1` zooms in, `<1` zooms out
|
||||
|
||||
```ludic
|
||||
program Demo {
|
||||
property Cam { z: fixed = 1.0 }
|
||||
model View { Cam }
|
||||
handler DrawWorld phase Render {
|
||||
Camera.zoom(2.0)
|
||||
Screen.fill_rectangle(150, 110, 20, 20, 0xffcc00)
|
||||
Screen.show()
|
||||
}
|
||||
}
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue