Scaling game while keeping original height or width, depending on display ratio

I’m working on a puzzle game and it’s using scale: mode: Phaser.Scale.FIT which works fine. But in most cases you either have black or empty bars on either the sides or at the top&bottom.

Is it possible to have Phaser3 resize the game canvas and either match the width or the height based on the display ratio? So only adjust the game height or width so that it scales to fit the entire window. It should maintain either the original game height or the original game width (again, based on the display ratio).

Not sure if I’m describing it clearly, see what I mean in screenshot below
phaser3_canvas_stretch

For example the game resolution is 480 x 640, so when the actual device display is:

  • 768 x 1280 then canvas should be → 480 x 800
  • 1920 x 1080 then canvas should be → 1138 x 640

Btw I know I would have to rearrange the layout in code, so change positions of game items/buttons/texts etc, that is fine. Also it doesn’t necessarily have to be completely dynamic, if it only adjusts at startup then that is good enough.

I was looking at this thread but that’s different question, and this StackOverflow question
seems to be based on Phaser2, I couldn’t get the code given in the answer to work in Phaser3.

I tried this code in the create() function of my first Boot scene, but that doesn’t seen to work :thinking:

create ()
{
    debugger;
    if (window.innerWidth / window.innerHeight > (480.0 / 640.0) )
    {
        // display is wider than tall, adjust the width to avoid black bars on sides
        this.game.config.width = 640.0 * (window.innerWidth / window.innerHeight);
    }
    else
    {
        // display is taller than wide, adjust the height to avoid black bars on top/bottom
        this.game.config.height = 480.0 * (window.innerHeight / window.innerWidth);
    }
    //NOTE this doesn't work! it should resize the canvas
    this.game.scale.refresh()

    this.scene.start('Preloader');
}

I tried using the this.game.scale.resize and some other code, see below. This does seem to change the internal game resolution correctly, but now it’s all squashed. I think the problem is that the canvas isn’t refreshed, so it still has the same 480x640 aspect ratio.

When I “unsquash” the game area in an image editor, then it does look to have the correct aspect ratio. So how do I resize the canvas? :thinking: Setting the this.game.canvas.style.width in the code below doesn’t seem to work

    create ()
    {
        var xsize = 480;
        var ysize = 640;
        var xdisplay = window.innerWidth;
        var ydisplay = window.innerHeight;
        if (xdisplay / ydisplay > (xsize / ysize) )
        {
            // display is wider than tall, adjust the width to avoid black bars on sides
            xsize = ysize * (xdisplay / ydisplay);
        }
        else
        {
            // display is taller than wide, adjust the height to avoid black bars on top/bottom
            ysize = xsize * (ydisplay / xdisplay);
        }
        this.game.scale.resize(xsize, ysize);
        this.game.canvas.style.width = xsize + 'px';
        this.game.canvas.style.height = ysize + 'px';
        this.game.scale.refresh();
        //NOTE this doesn't work! the canvas isn't resized(?)
    }

Change

-this.game.scale.resize(xsize, ysize);
-this.game.canvas.style.width = xsize + 'px';
-this.game.canvas.style.height = ysize + 'px';
-this.game.scale.refresh();
+this.game.scale.setGameSize(xsize, ysize);
2 Likes
let xdisplay = window.innerWidth;
let ydisplay = window.innerHeight;

let xsize = 480;
let ysize = 640;

let new_width, new_height;

if (xdisplay / ydisplay > xsize / ysize) {
	new_width = ysize * xdisplay / ydisplay;
	new_height = ysize;
} else {
	new_width = xsize;
	new_height = xsize * ydisplay / xdisplay;
}

new_width = Math.max(new_width, xsize);
new_height = Math.max(new_height, ysize);

this.game.scale.setZoom(ydisplay / new_height);

this.game.scale.resize(new_width, new_height);
this.game.scale.refresh()

@samme Thank, using game.scale.setGameSize did the trick :+1:

Just want to mention that I still had a small border around the game area. To get rid of that border you can add the CSS as mentioned in this thread in your index.html.

<style>
    body {
      overflow: hidden;
      padding: 0px;
      margin: 0px;
    }
</style>