Hi!
Here is the code to reproduce the issue
import UIPlugin from '../../templates/ui/ui-plugin.js';
// LAYOUT
const SCALE = window.devicePixelRatio
const SCREEN_WIDTH = window.innerWidth*SCALE
const SCREEN_HEIGHT = window.innerHeight*SCALE
const MENU = {
x: SCREEN_WIDTH/2,
y: SCREEN_HEIGHT/2,
w: 775*SCALE,
h: 531*SCALE,
border: 115,
safe: {left: 45, top: 75, right: 55, bottom: 80}, // left, top, right, bottom
border_scale: 1,
}
// SCENE
class Demo extends Phaser.Scene {
constructor() {
super({
key: 'examples'
})
}
preload() {
this.load.image('menu', 'https://i.ibb.co/6gmTJWN/menu.png'); // 775x531
}
create() {
this.addNinePatchFixed(MENU.x, MENU.y, MENU.w, MENU.h, MENU.border)
this.rexUI.add.roundRectangle(
MENU.x-MENU.w/2+MENU.safe.left*MENU.border_scale, // x
MENU.y-MENU.h/2+MENU.safe.top*MENU.border_scale, // y
MENU.w-MENU.safe.right*MENU.border_scale*2, // w
MENU.h-MENU.safe.bottom*MENU.border_scale*2, // h
0,
0x00ff00,
0.4)
.setDepth(10).setOrigin(0, 0);
}
addNinePatchFixed(x, y, w, h, value) {
return this.rexUI.add.ninePatch({
x: x, y: y,
width: w, height: h,
key: 'menu',
columns: [value, undefined, value],
rows: [value, undefined, value],
stretchMode: 0
}).setOrigin(0.5, 0.5)
}
}
// GAME
var config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: SCREEN_WIDTH,
height: SCREEN_HEIGHT,
scale: {
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_BOTH,
},
plugins: {
scene: [{
key: 'rexUI',
plugin: UIPlugin,
mapping: 'rexUI'
}]
},
scene: Demo,
};
var game = new Phaser.Game(config);
You have to run this code locally, then go to browser and reload page with different DPR settings (1,2,3):
DPR1
DPR2
DPR3
So here is the issue - since I am making responsive games that have to not look blurry on high-dpr (retina) displays my Phaser game width
, height
should be equal to window.innerWidth*window.devicePixelRation
x window.innerHeight*window.devicePixelRation
- that means game resizes to fully fit the device screen. Then because of game.config.scale.mode = Phaser.Scale.FIT the canvas will be resized to window.innerWidth
x window.innerHeight
.
Since the ninepatch border is never scaled and being set as absolute value, its size will be different on screens with different DPR, that's what screenshots prove. Seems like I can not affect this border scale, but I definetely need to do it. For example on DPR=2 screen I want my border to be x2
-scaled to visually appear same size as on DPR=1 screen. Same for DPR=3 screen - my border should be scaled x3
there is a way I tried to solve that issue by scaling the ninepatch with setScale(SCALE)
after initialization:
import UIPlugin from '../../templates/ui/ui-plugin.js';
// LAYOUT
const SCALE = window.devicePixelRatio
const SCREEN_WIDTH = window.innerWidth*SCALE
const SCREEN_HEIGHT = window.innerHeight*SCALE
const MENU = {
x: SCREEN_WIDTH/2,
y: SCREEN_HEIGHT/2,
w: 775,
h: 531,
border: 115,
safe: {left: 45, top: 75, right: 55, bottom: 80}, // left, top, right, bottom
}
// SCENE
class Demo extends Phaser.Scene {
constructor() {
super({
key: 'examples'
})
}
preload() {
this.load.image('menu', 'https://i.ibb.co/6gmTJWN/menu.png'); // 775x531
}
create() {
this.addNinePatchFixed(MENU.x, MENU.y, MENU.w, MENU.h, MENU.border).setScale(SCALE);
this.rexUI.add.roundRectangle(
MENU.x-15, // x
MENU.y-5, // y
MENU.w-MENU.safe.right-MENU.safe.left, // w
MENU.h-MENU.safe.bottom-MENU.safe.top, // h
0,
0x00ff00,
0.4)
.setDepth(10).setScale(SCALE);
}
addNinePatchFixed(x, y, w, h, value) {
return this.rexUI.add.ninePatch({
x: x, y: y,
width: w, height: h,
key: 'menu',
columns: [value, undefined, value],
rows: [value, undefined, value],
stretchMode: 0
}).setOrigin(0.5, 0.5)
}
}
// GAME
var config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: SCREEN_WIDTH,
height: SCREEN_HEIGHT,
scale: {
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_BOTH,
},
plugins: {
scene: [{
key: 'rexUI',
plugin: UIPlugin,
mapping: 'rexUI'
}]
},
scene: Demo,
};
var game = new Phaser.Game(config);
There is a mess in my head after a long workday so I will try to look into that once again tomorrow. Scenario 2 seems working, but I don't like something about it intuitively but cant figure out what's wrong at the moment.
Any help or ideas in solving that task will be highly appreciated. Thanks in advance!