From 59b391e9838916442999c63c04c9f554aa86f13b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Tue, 4 May 2021 14:08:40 +0200 Subject: [PATCH] Prevent WA scale manager from zooming too much --- front/src/Phaser/Services/HdpiManager.ts | 39 ++++++++++++++++--- front/src/Phaser/Services/WaScaleManager.ts | 6 +-- front/src/index.ts | 2 +- .../tests/Phaser/Services/HdpiManagerTest.ts | 27 ++++++++++++- 4 files changed, 63 insertions(+), 11 deletions(-) diff --git a/front/src/Phaser/Services/HdpiManager.ts b/front/src/Phaser/Services/HdpiManager.ts index 1cc97634..96bc0f40 100644 --- a/front/src/Phaser/Services/HdpiManager.ts +++ b/front/src/Phaser/Services/HdpiManager.ts @@ -8,7 +8,12 @@ interface Size { export class HdpiManager { private _zoomModifier: number = 1; - public constructor(private minGamePixelsNumber: number) { + /** + * + * @param minRecommendedGamePixelsNumber The minimum number of pixels we want to display "by default" to the user + * @param absoluteMinPixelNumber The very minimum of game pixels to display. Below, we forbid zooming more + */ + public constructor(private minRecommendedGamePixelsNumber: number, private absoluteMinPixelNumber: number) { } /** @@ -24,7 +29,7 @@ export class HdpiManager { const realPixelNumber = realPixelScreenSize.width * realPixelScreenSize.height; // If the screen has not a definition small enough to match the minimum number of pixels we want to display, // let's make the canvas the size of the screen (in real pixels) - if (realPixelNumber <= this.minGamePixelsNumber) { + if (realPixelNumber <= this.minRecommendedGamePixelsNumber) { return { game: realPixelScreenSize, real: realPixelScreenSize @@ -34,7 +39,7 @@ export class HdpiManager { let i = 1; while (true) { - if (realPixelNumber <= this.minGamePixelsNumber * i * i) { + if (realPixelNumber <= this.minRecommendedGamePixelsNumber * i * i) { break; } @@ -58,10 +63,34 @@ export class HdpiManager { } } + const gameWidth = Math.ceil(realPixelScreenSize.width / (i - 1) / this._zoomModifier); + const gameHeight = Math.ceil(realPixelScreenSize.height / (i - 1) / this._zoomModifier); + + // Let's ensure we display a minimum of pixels, even if crazily zoomed in. + if (gameWidth * gameHeight < this.absoluteMinPixelNumber) { + const minGameHeight = Math.sqrt(this.absoluteMinPixelNumber * realPixelScreenSize.height / realPixelScreenSize.width); + const minGameWidth = Math.sqrt(this.absoluteMinPixelNumber * realPixelScreenSize.width / realPixelScreenSize.height); + + // Let's reset the zoom modifier (WARNING this is a SIDE EFFECT in a getter) + this._zoomModifier = realPixelScreenSize.width / minGameWidth / (i - 1); + + return { + game: { + width: minGameWidth, + height: minGameHeight, + }, + real: { + width: realPixelScreenSize.width, + height: realPixelScreenSize.height, + } + } + + } + return { game: { - width: Math.ceil(realPixelScreenSize.width / (i - 1) / this._zoomModifier), - height: Math.ceil(realPixelScreenSize.height / (i - 1) / this._zoomModifier), + width: gameWidth, + height: gameHeight, }, real: { width: Math.ceil(realPixelScreenSize.width / (i - 1)) * (i - 1), diff --git a/front/src/Phaser/Services/WaScaleManager.ts b/front/src/Phaser/Services/WaScaleManager.ts index 05689071..77395675 100644 --- a/front/src/Phaser/Services/WaScaleManager.ts +++ b/front/src/Phaser/Services/WaScaleManager.ts @@ -7,8 +7,8 @@ class WaScaleManager { private hdpiManager: HdpiManager; private scaleManager!: ScaleManager; - public constructor(private minGamePixelsNumber: number) { - this.hdpiManager = new HdpiManager(minGamePixelsNumber); + public constructor(private minGamePixelsNumber: number, private absoluteMinPixelNumber: number) { + this.hdpiManager = new HdpiManager(minGamePixelsNumber, absoluteMinPixelNumber); } public setScaleManager(scaleManager: ScaleManager) { @@ -44,4 +44,4 @@ class WaScaleManager { } } -export const waScaleManager = new WaScaleManager(640*480); +export const waScaleManager = new WaScaleManager(640*480, 196*196); diff --git a/front/src/index.ts b/front/src/index.ts index 0bc7310d..79997b76 100644 --- a/front/src/index.ts +++ b/front/src/index.ts @@ -69,7 +69,7 @@ switch (phaserMode) { throw new Error('phaserMode parameter must be one of "auto", "canvas" or "webgl"'); } -const hdpiManager = new HdpiManager(640*480); +const hdpiManager = new HdpiManager(640*480, 196*196); const { game: gameSize, real: realSize } = hdpiManager.getOptimalGameSize({width, height}); const config: GameConfig = { diff --git a/front/tests/Phaser/Services/HdpiManagerTest.ts b/front/tests/Phaser/Services/HdpiManagerTest.ts index 2a4d2662..4e0787a7 100644 --- a/front/tests/Phaser/Services/HdpiManagerTest.ts +++ b/front/tests/Phaser/Services/HdpiManagerTest.ts @@ -3,7 +3,7 @@ import {HdpiManager} from "../../../src/Phaser/Services/HdpiManager"; describe("Test HdpiManager", () => { it("should match screen size if size is too small.", () => { - const hdpiManager = new HdpiManager(640*480); + const hdpiManager = new HdpiManager(640*480, 64*64); const result = hdpiManager.getOptimalGameSize({ width: 320, height: 200 }); expect(result.game.width).toEqual(320); @@ -13,7 +13,7 @@ describe("Test HdpiManager", () => { }); it("should match multiple just above.", () => { - const hdpiManager = new HdpiManager(640*480); + const hdpiManager = new HdpiManager(640*480, 64*64); let result = hdpiManager.getOptimalGameSize({ width: 960, height: 600 }); expect(result.game.width).toEqual(960); @@ -29,4 +29,27 @@ describe("Test HdpiManager", () => { expect(result.real.width).toEqual(result.game.width * 3); expect(result.real.height).toEqual(result.game.height * 3); }); + + it("should not zoom in too much.", () => { + const hdpiManager = new HdpiManager(640*480, 64*64); + + hdpiManager.zoomModifier = 11; + + let result = hdpiManager.getOptimalGameSize({ width: 640, height: 640 }); + expect(result.game.width).toEqual(64); + expect(result.game.height).toEqual(64); + expect(hdpiManager.zoomModifier).toEqual(10); + + }); + + it("should not zoom out too much.", () => { + const hdpiManager = new HdpiManager(640*480, 64*64); + + hdpiManager.zoomModifier = 1/10; + + let result = hdpiManager.getOptimalGameSize({ width: 1280, height: 768 }); + expect(result.game.width).toEqual(1280); + expect(result.game.height).toEqual(768); + expect(hdpiManager.zoomModifier).toEqual(1); + }); });