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
@@ -6,7 +6,7 @@ import { type FederatedPointerEvent, Text } from 'pixi.js';
|
||||
import { isSymbolType } from '../../core/model/AssetTypes';
|
||||
import type { EditorState } from '../state';
|
||||
import type { World } from '../../runtime/World';
|
||||
import { textStyle } from '../../ui';
|
||||
import { textStyle, ui } from '../../ui';
|
||||
import { type ActiveCamera, cameraOfItems, cameraOfWorld } from '../../viewport/activeCamera';
|
||||
import { collectHolderItems, collectWorldItems } from '../../viewport/items';
|
||||
import {
|
||||
@@ -31,7 +31,7 @@ export class GameViewport extends WorldViewport {
|
||||
private playWorld: World | null = null;
|
||||
/** The editor run's world: it takes the mouse, but it is never what this view draws. */
|
||||
private editorWorld: World | null = null;
|
||||
/** Screen pixels per camera pixel as last drawn, null without a camera. */
|
||||
/** Device pixels per camera pixel as last drawn, null without a camera. */
|
||||
private factor: number | null = null;
|
||||
/** Told the factor of every redraw: auto and fit change with the view. */
|
||||
onScaleShown: ((factor: number | null) => void) | null = null;
|
||||
@@ -92,8 +92,9 @@ export class GameViewport extends WorldViewport {
|
||||
|
||||
protected override currentView(): View | null {
|
||||
const camera = this.activeCamera();
|
||||
this.factor = camera ? cameraFactor(camera.props, this.w, this.h, this.scaleMode) : null;
|
||||
return camera ? cameraView(camera, this.w, this.h, this.scaleMode) : null;
|
||||
const ratio = ui().app.renderer.resolution;
|
||||
this.factor = camera ? cameraFactor(camera.props, this.w, this.h, this.scaleMode, ratio) : null;
|
||||
return camera ? cameraView(camera, this.w, this.h, this.scaleMode, ratio) : null;
|
||||
}
|
||||
|
||||
private activeCamera(): ActiveCamera | null {
|
||||
@@ -106,8 +107,8 @@ export class GameViewport extends WorldViewport {
|
||||
}
|
||||
|
||||
/**
|
||||
* Screen pixels per camera pixel and per world unit, and the camera's picture as it lies on
|
||||
* screen, in global pixels; null without a camera.
|
||||
* Device pixels per camera pixel, CSS pixels per world unit, and the camera's picture as it
|
||||
* lies on screen, in global CSS pixels; null without a camera.
|
||||
*/
|
||||
scaleInfo(): {
|
||||
factor: number;
|
||||
|
||||
Reference in new issue
Block a user