Prevent WA scale manager from zooming too much

This commit is contained in:
David Négrier 2021-05-04 14:08:40 +02:00
parent 613ff5d463
commit 59b391e983
4 changed files with 63 additions and 11 deletions

View File

@ -8,7 +8,12 @@ interface Size {
export class HdpiManager { export class HdpiManager {
private _zoomModifier: number = 1; 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; 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, // 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) // let's make the canvas the size of the screen (in real pixels)
if (realPixelNumber <= this.minGamePixelsNumber) { if (realPixelNumber <= this.minRecommendedGamePixelsNumber) {
return { return {
game: realPixelScreenSize, game: realPixelScreenSize,
real: realPixelScreenSize real: realPixelScreenSize
@ -34,7 +39,7 @@ export class HdpiManager {
let i = 1; let i = 1;
while (true) { while (true) {
if (realPixelNumber <= this.minGamePixelsNumber * i * i) { if (realPixelNumber <= this.minRecommendedGamePixelsNumber * i * i) {
break; 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 { return {
game: { game: {
width: Math.ceil(realPixelScreenSize.width / (i - 1) / this._zoomModifier), width: gameWidth,
height: Math.ceil(realPixelScreenSize.height / (i - 1) / this._zoomModifier), height: gameHeight,
}, },
real: { real: {
width: Math.ceil(realPixelScreenSize.width / (i - 1)) * (i - 1), width: Math.ceil(realPixelScreenSize.width / (i - 1)) * (i - 1),

View File

@ -7,8 +7,8 @@ class WaScaleManager {
private hdpiManager: HdpiManager; private hdpiManager: HdpiManager;
private scaleManager!: ScaleManager; private scaleManager!: ScaleManager;
public constructor(private minGamePixelsNumber: number) { public constructor(private minGamePixelsNumber: number, private absoluteMinPixelNumber: number) {
this.hdpiManager = new HdpiManager(minGamePixelsNumber); this.hdpiManager = new HdpiManager(minGamePixelsNumber, absoluteMinPixelNumber);
} }
public setScaleManager(scaleManager: ScaleManager) { 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);

View File

@ -69,7 +69,7 @@ switch (phaserMode) {
throw new Error('phaserMode parameter must be one of "auto", "canvas" or "webgl"'); 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 { game: gameSize, real: realSize } = hdpiManager.getOptimalGameSize({width, height});
const config: GameConfig = { const config: GameConfig = {

View File

@ -3,7 +3,7 @@ import {HdpiManager} from "../../../src/Phaser/Services/HdpiManager";
describe("Test HdpiManager", () => { describe("Test HdpiManager", () => {
it("should match screen size if size is too small.", () => { 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 }); const result = hdpiManager.getOptimalGameSize({ width: 320, height: 200 });
expect(result.game.width).toEqual(320); expect(result.game.width).toEqual(320);
@ -13,7 +13,7 @@ describe("Test HdpiManager", () => {
}); });
it("should match multiple just above.", () => { 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 }); let result = hdpiManager.getOptimalGameSize({ width: 960, height: 600 });
expect(result.game.width).toEqual(960); 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.width).toEqual(result.game.width * 3);
expect(result.real.height).toEqual(result.game.height * 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);
});
}); });