Commit Graph
2 Commits
Author SHA1 Message Date
adminandClaude Opus 5.5 1665576fb9 Let a pixel perfect camera draw on the game view's pixel grid
game-maker / gate (push) Successful in 3m6s
game-maker / suite (push) Successful in 16m1s
A camera that follows smoothly stands between pixels most of the time,
and pixel art then wanders between them. The new camera switch draws
what the camera shows on the game view's own grid, while positions in
the model keep their fractions.

- `Pixel perfect` is a camera row, off by default. It works at every
  fixed game scale and at Auto, but not at Fit and not in the Scene
  tab, where one works with the fractions.
- The grid has one step per device pixel of a world unit. At 100% that
  is whole units, at 500% fifths. The view carries it (`View.grid`),
  so no view draws with the grid of another.
- The view looks from a point that puts the world's origin on a whole
  device pixel (`lookFrom`). This also covers odd camera sizes and
  views that cut the picture to an odd size.
- Sprites, texts and tilemaps snap their top left corner when they are
  unturned, so an odd size lands on whole pixels too. A turned object
  snaps its pivot (`snapPlacement` in `pixelGrid.ts`).
- Under a camera shader the picture is taken the same way, and the
  objects in it use the picture's grid. With Camera pixels that is one
  step per camera pixel.
- An overlay camera has its own switch and snaps only while the main
  picture is at a fixed scale.
- Particles are drawn where they are.
- New test hook `__gm.gameDrawnRect(id)` reads where a sprite's picture
  is drawn, which `gameRect` (the model's) cannot tell.

Found: the e2e fixture at 300% drew the crate at y 205.5 device pixels
without moving the camera, because the view cut to an odd height puts
its centre on half a pixel. With the switch on it is at 206.

Tests:
- Gate: 237 files, 3587 tests (+10 in pixel-grid.test.ts)
- e2e 2,3: ALL PASSED, 75 checks (+1, 3j)
- Counter-checks: without the origin snap 3 unit tests fail, with the
  centre snapped instead of the corner 2 fail

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 13:30:31 +02:00
adminandClaude Opus 5.5 2e55071fa5 Lay a shader over a camera's whole picture (#299)
game-maker / gate (push) Successful in 3m2s
game-maker / suite (push) Successful in 14m59s
A shader so far worked only on its own wearer. Effects over the whole
game picture, such as a vignette, grey, scanlines or a red flash on a
hit, had no place to live. A camera now wears one, drawn the way a
field shader of a particle source is (#170).

- The camera gets a Shader row and, while one is picked, a Shader
  resolution row. The shader's properties follow as camera rows. They
  load, animate and appear in a Properties node under Type Camera.
- Every view keeps masks and objects in one container. CameraShade
  renders it into the camera's picture, cleared to the background,
  and draws the shader over the frame. Game tab and play.html take
  the container off the stage while the picture stands in for it.
- Screen pixels gives the picture as many pixels as it covers on
  screen. Camera pixels uses View width x View height and scales up
  without smoothing.
- A pixel counts as a camera pixel in both (the user's choice). The
  uniform uPixelScale makes Texture size read View width x View
  height, so a Blur keeps its reach at any game scale.
- Each camera wears its own shader, overlay cameras included. A red
  flash on the game camera leaves the HUD of an overlay camera alone.
- The scene view's eye has a Shader switch on the Camera row, off by
  default. With it on, the main camera's shader lies over its frame,
  below symbols and gizmos, and the world around it stays drawn.
- New tool tools/perf-camera-shader.mjs measures the cost.

Measured on stein2 (HD 630, Game tab at Fit 1310x679): a camera
shader that hands the picture through stays inside the scene's own
spread of 3 to 5 fps between runs. A Blur of 4 cost 4 to 8 fps.

Tests:
- Gate on melektaus-atx: 227 files, 3497 tests (3487 + 10).
- e2e 63 alone: 11 checks (6 + 5), e2e sum 1725 counted.
- 63e-63i: pass-through is byte-equal and upright at 100%, flat red
  reaches the corners while the overlay keeps its green, Texture
  size reads 640 x 360 in both resolutions at Fit, no shader draws
  as before, and the scene view shows it only with the switch on.
- Counter-checks: a camera left out of the shader wearers fails 1
  unit test. Counting screen pixels fails 63g with #ab6000.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 16:03:09 +02:00