Skip to content

Camera: offset shifts the view for good, and a shake keeps it - #1768

Merged
obiot merged 1 commit into
masterfrom
fix/camera-offset
Oct 26, 2026
Merged

obiot merged 1 commit into
masterfrom
fix/camera-offset

Conversation

@obiot

@obiot obiot commented Oct 25, 2026

Copy link
Copy Markdown
Member

Summary

Camera2d#offset becomes the one field for both a lasting look offset (above the hero, ahead of where he faces) and the shake. It was documented as "offset for shake effect" and only the shake used it: the built-in shake wrote random values into it and zeroed it when done, so any offset a game set was wiped by the next shake.

app.viewport.follow(hero, app.viewport.AXIS.BOTH, 0.1);
app.viewport.offset.set(0, -70); // look a little above the feet

Changes

  • Shake: adds its jitter on top of the game's offset and gives that value back exactly when it ends. This also holds when the game changes the offset mid-shake, when the shake is removed or replaced early, or when two shakes run at once (they add up). The bookkeeping stays inside ShakeEffect; there is no new field on the camera.

  • Everything that works out what the camera shows now counts the offset:

    • culling (worldView)
    • the pointer (localToWorld, worldToLocal)
    • tile layers, which picked their tiles from the camera position alone and left a strip undrawn under a lasting offset (all render paths: shader, pre-rendered, tile by tile)
    • parallax ImageLayers

    Drawing, lights and fog already counted it.

  • reset() clears the offset, so it does not leak from one scene into the next.

  • The offset JSDoc is rewritten with an example, and the camera skill gains a section on framing the target off centre.

Behaviour change: parallax backgrounds now shake along with the world, scaled by their ratio. Before, they stood still during a shake. A background with ratio 0 is unaffected. The offset is applied after the camera's bounds, so the view can show past them.

Testing

  • tests/camera-offset.spec.js (21 tests). It covers:

    • the shake keeping the offset, including a change mid-shake, early removal, a forced replacement, two stacked shakes, reset() mid-shake and a persistent shake
    • culling and the pointer round trip, with zoom, screen position and roll
    • tile layers drawing the full shifted view, tile by tile and pre-rendered
    • parallax position

    15 deliberately broken versions of the code were all caught.

  • The full suite passes (8,788 tests) and pnpm lint passes.

  • In the browser, every map of the Tiled map loader example on Canvas, WebGL and WebGPU, at zoom 1, 0.5 and 2: the camera at P with offset O draws the same frame, pixel for pixel, as the camera moved to P + O with no offset. With tile layers blind to the offset (the old code), 10 of the 12 maps had missing tiles.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SeWCkETjW35ZbXDRswV1hx

`Camera2d#offset` is now the one field for both a lasting look offset
(above the hero, ahead of him) and the shake. The built-in shake used to
write random values into it and zero it when done, wiping any offset the
game had set. It now adds its jitter on top of the game's value and gives
that value back exactly when it ends, also when the game changes the
offset mid-shake, when the shake is removed or replaced early, or when two
shakes run at once.

Everything that works out what the camera shows now counts the offset:
culling (`worldView`), the pointer (`localToWorld`, `worldToLocal`), tile
layers (which picked their tiles from the camera position alone and left a
strip undrawn) and parallax `ImageLayer`s. `reset()` clears it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SeWCkETjW35ZbXDRswV1hx
Copilot AI balanced review requested due to automatic review settings October 25, 2026 23:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

@obiot
obiot merged commit a1e952f into master Oct 26, 2026
6 checks passed
@obiot
obiot deleted the fix/camera-offset branch October 26, 2026 00:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants