Keep game view steps pixel exact under Windows display scaling
At 125% Windows scaling the game view drew 100% as 1.25 screen pixels per camera pixel, so pixel art showed texels of uneven width even at the round steps. The steps now count device pixels instead of CSS pixels. - gameScaleFactor, cameraFactor and cameraView take the device pixel ratio. 100% is one screen pixel per camera pixel, 200% two. - Auto picks the largest step that fits in device pixels. Fit reports its factor in device pixels too, e.g. 156% at 125% scaling. - Fixed steps start the frame on a whole device pixel. - The game view reads the ratio from the renderer resolution. Limits: main.ts caps the resolution at 2, so scaling above 200% is stretched by the browser again. A changed ratio at runtime only counts after a reload, as before. Tests: - 2 unit tests at 125%: 100% is one device pixel on a whole pixel, auto and fit count device pixels. - Counter-check: without the conversion the 100% test fails. - check.sh: 156 files, CHECK EXIT 0 on the combined working tree. - No e2e: the harness runs at devicePixelRatio 1, same math as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2592873d76
commit
22a89ed0f0
3 files changed
+48
-15
No files matched your search
@@ -88,6 +88,26 @@ describe('cameraView with a zoomed camera', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('cameraView under Windows scaling at 125%', () => {
|
||||
const plain = { x: 0, y: 0, props: { width: 640, height: 360, zoom: 1 } };
|
||||
|
||||
it('100% is one device pixel per camera pixel, starting on a whole device pixel', () => {
|
||||
const view = cameraView(plain, 801, 601, 1, 1.25);
|
||||
expect(view.scale * 1.25).toBeCloseTo(1, 12);
|
||||
expect(view.rect.w).toBeCloseTo(512, 12);
|
||||
expect(view.rect.h).toBeCloseTo(288, 12);
|
||||
expect(view.rect.x * 1.25).toBeCloseTo(181, 9);
|
||||
expect(view.rect.y * 1.25).toBeCloseTo(196, 9);
|
||||
});
|
||||
|
||||
it('auto picks the step in device pixels, and fit reports device pixels', () => {
|
||||
expect(cameraFactor(plain.props, 1100, 700, 'auto', 1.25)).toBe(2);
|
||||
expect(cameraFactor(plain.props, 1100, 700, 'auto')).toBe(1);
|
||||
expect(cameraFactor(plain.props, 800, 600, 'fit', 1.25)).toBeCloseTo(1.5625, 9);
|
||||
expect(cameraView(plain, 800, 600, 'fit', 1.25).scale).toBeCloseTo(1.25, 9);
|
||||
});
|
||||
});
|
||||
|
||||
describe('gameScaleFactor', () => {
|
||||
it('fit is the exact factor that fills the tighter side', () => {
|
||||
expect(gameScaleFactor('fit', 640, 360, 800, 600)).toBeCloseTo(1.25, 9);
|
||||
|
||||
Reference in new issue
Block a user