Scaling Phaser 3 Game Screens Easy Example

Stephen Garside | Thu 27 Feb 20 > 2 min read

The The Phaser 3 Game Engine has its own in-built scale manager, but what if you want to write your own simple custom Phaser 3 game scaling plugin with breakpoints etc? The code below will enable you to achieve a scaling effect demonstrated in the following screens:

Mobile

Phaser 3 Scaled Game Small

Tablet

Phaser 3 Scaled Game Med

Desktop

Phaser 3 Scaled Game Large

The first step is to extend the Phaser 3 Scene class with your own custom class as follows:

export default class SceneBase extends Phaser.Scene 
{
    constructor(config) {
        super(config);
        
        this.gameContainer = document.getElementById('game-container');
        this.eventEmitter = new Phaser.Events.EventEmitter();
    }
    
    preload() {
    }
    
    create() {
    }
    
    update() {
    }
    
    resizeGameContainer() {
        let winW = window.innerWidth / window.devicePixelRatio;
        let winH = window.innerHeight / window.devicePixelRatio;
        let breakpoints = [{ scrW: 0, gamW: 400 }, { scrW: 600, gamW: 450 }, { scrW: 900, gamW: 550 }, { scrW: 1200, gamW: 750 }, { scrW: 1500, gamW: 1000 }, { scrW: 1800, gamW: 1300 }];
        let currentBreakpoint = null;
        let newViewPortW = 0;
        let newViewPortH = 0;
        
        for (let i = 0; i < breakpoints.length; i++) 
        {
            currentBreakpoint = breakpoints[i];
            
            if (winW < currentBreakpoint.scrW) 
            {
                break;
            }
        }
    
        newViewPortW = currentBreakpoint.gamW;
        newViewPortH = currentBreakpoint.gamW * (winH / winW);
        
        this.game.scale.resize(newViewPortW, newViewPortH);
this.gameContainer.style.width = `${window.innerWidth}px`; this.gameContainer.style.height = `${window.innerHeight}px`; this.game.canvas.style.width = `${window.innerWidth}px`; this.game.canvas.style.height = `${window.innerHeight}px`;
this.eventEmitter.emit('screenResized'); } }

In the constructor we need to get a reference to your top level game container div - in my example I have given it an id of game-container.  The next step is to create a base EventEmitter - this will be used to emit a screenResized event that you can hook into throughout your game to re-position objects in your scene if required.

The code above basically takes the window dimensions, does a lookup in a breakpoints array to find the nearest matching game width before scaling the Phaser 3 game to a new size.  Notice I take into account the devicePixelRatio, as without it your game wont scale as you expect on screens with denser pixel ratios (than 1).

All your Phaser 3 game scenes should then inherit from the base scene you have just created:

class SceneMain extends SceneBase {

Any scenes that inherit from your baseScene class can now listen out for the screenResized event and re-position elements on screen, for example joystick buttons, text etc.

createEventListeners() 
{
    this.eventEmitter.on('screenResized', () => { this.onScreenResize(); });
}

The final step is to create a standard javascript event listener to listen for the browser window being resized. On window resize, the above logic loops through all the scenes in your Phaser 3 game and calls the resizeGameContainer event on the baseScene class.

var game = new Phaser.Game(config);
window.addEventListener('load', () => { window.addEventListener('resize', event => { for (let i = 0; i < game.scene.scenes.length; i++) { game.scene.scenes[i].resizeGameContainer(); } }); });

And there you have it - a simple, easy example of how to implement a Phaser 3 screen scaling plugin that gives you full control over your game size on portrait and landscape orientations across mobile, tablet and desktop screens!

Leave Your Comments...