How do I scale my game in Phaser?

How do I scale my game in Phaser?

One of the many questions I’ve seen asked is “How do I scale my game in Phaser?”. I have seen a lot of different answers to this query. I’m not saying any of the other answers you will find out there are wrong. What I will say, is this is how I do it, and that has worked well for me so far. One of the nice things about my job (at gaiaonline.com) is that we get hundreds of thousands of plays on the games and our users are not shy about complaining. When there are problems I have been able to refine my code based on their feedback.

Why won’t my game fit on my phone?

The problem lies not within Phaser itself but rather the different sizes of phone screens. Those of us who have been making web games for some time are used to just building a game that will fit most monitors that were made in the last 10 years. For years the standard was 800 x 600. Then came mobile. Instead of our work area getting bigger it shrank. We now had dozens or screen sizes to contend with.

So what code do I use to scale my game?

Unfortunately, there is not one single line of code to make your game responsive. There are two steps I follow to making a game that will run on desktop and most phones.

  1. planning
  2. maths

*(maths, my fellow Americans, is how the rest of the English-speaking world refers to math. You’ll get used to it)

Making the canvas fit the phone

For a desktop game in portrait mode, I usually use

game = new Phaser.Game(480, 640, Phaser.AUTO, "ph_game");

For a mobile portrait mode, I set the dimensions dynamically

game = new Phaser.Game(window.innerWidth, window.innerHeight, Phaser.AUTO, "ph_game");

You can see more about this and about how to detect mobile in the starter snippets or my Phaser Templates

Planning Out for scaling

The size of a game will vary on each different device, but we do have some constants to work with. From the start of planning a game in my head, I start thinking about where each part will go in relation to the borders of the game. One of the things I rarely do is to set a stationary sprite, image or a textfield by a number. For example instead of

this.scoreText.x=240;

which would place the text in the middle of a game 480 pixels wide. I would use half the width

this.scoreText.x=game.width/2;

In my opinion, to make the move from desktop to mobile we need to start thinking in terms of ratios and borders rather than static values.

Positioning Formulas

Here are some of the formulas I use to position sprites.

This assumes the sprite has an anchor of 0.5, on both x and y anchors.

Center

obj.x = game.width / 2;
obj.y = game.height / 2;

Align to Bottom

obj.y = game.height - obj.height / 2;

Percentage from top- where the variable percent is a number from 0 to .99

obj.y=game.height*percent;

Percentage from bottom

obj.y = game.height - (game.height * percent);

Percentage from Right

obj.x = game.width - (game.width * percent);

Percentage from Left

obj.x = game.width * percent;

Percentage from Center

obj.x = game.width / 2 - (game.width * percent);
obj.x -= obj.width / 2;

To position sprites with an anchor int the top left corner, or to position groups I subtract half of the width of the sprite/group

Center a group

obj.x = game.width / 2 - obj.width / 2;
obj.y = game.height / 2 - obj.height / 2;

Scaling

I try to keep scaling to a minimum in my games, but sometimes, especially for the Ipad it is necessary.

I like to base the scaling using the width of the game as a constant.

First I make the game for desktop and get the sprite to game width ratio

console.log(obj.width/game.width);

Then I set the sprite by that ratio, on the desktop game this will have no effect

scaleToGameW(obj,percent)
    {
    	obj.width=game.width*percent;
    	obj.scale.y=obj.scale.x;
    }

obj.scale.y=obj.scale.x will keep the object proportional. For more about this see Scaling Objects Proportional in Phaser.

Here is an example:

I want to put three animals standing on the ground. I also want the sun in the middle of the game, and I want this to look right on every device.

How do I scale my game in Phaser?

Here is the code I will use to do that

var StateMain = {
    preload: function() {
        game.load.image("cow", "images/cow.png");
        game.load.image("elephant", "images/elephant.png");
        game.load.image("lion", "images/lion.png");
        game.load.image("sun","images/sun.png");
        game.load.image("ground", "images/ground.png");
    },
    create: function() {

    	//make the sky blue
    	game.stage.backgroundColor="#007fff";

    	this.ground = game.add.sprite(0, 0, "ground");
        this.elephant = game.add.sprite(0, 0, "elephant");
        this.cow = game.add.sprite(0, 0, "cow");
        this.lion = game.add.sprite(0, 0, "lion");
        this.sun=game.add.sprite(0,0,"sun");
        
        this.ground.anchor.set(0.5,0.5);
        this.elephant.anchor.set(0.5,0.5);
        this.cow.anchor.set(0.5,0.5);
        this.lion.anchor.set(0.5,0.5);
        this.sun.anchor.set(0.5,0.5);

        //use getScaleToGameW 
        //in desktop mode to get your percentages to 
     	//use in this.scaleToGameW
     	//this.getScaleToGameW(this.sun);
        
        //set the percentages
     	this.scaleToGameW(this.cow,.13);	
     	this.scaleToGameW(this.lion,.11);
     	this.scaleToGameW(this.elephant,.13);
     	this.scaleToGameW(this.sun,.27);

     	
     	
     	//stretch the ground to match the width of the game
        this.scaleToGameW(this.ground,1);

        //center the sun
        this.center(this.sun);

        //put the ground at the bottom
        this.alignToBottom(this.ground);
        this.centerH(this.ground);

        //put the cow on the bottom
        //and 10 percent from the left
        this.alignToBottom(this.cow);
        this.fromLeft(this.cow,.1);

        //put the lion on the bottom
        //and in the center of the screen
        this.alignToBottom(this.lion);
        this.centerH(this.lion);

        //put the elephant at the bottom
        //and 10 percent from the right
        this.alignToBottom(this.elephant);
        this.fromRight(this.elephant,.1);

    },
    update: function() {},
    getScaleToGameW(obj)
    {	
    	console.log(obj.width/game.width);
    },
    scaleToGameW(obj,percent)
    {
    	obj.width=game.width*percent;
    	obj.scale.y=obj.scale.x;
    },
    center: function(obj) {
        obj.x = game.width / 2;
        obj.y = game.height / 2;
    },
    centerH: function(obj) {
        obj.x = game.width / 2;
    },
    centerV: function(obj) {
        obj.y = game.height / 2;
    },
    centerGroup: function(obj) {
        obj.x = game.width / 2 - obj.width / 2;
        obj.y = game.height / 2 - obj.height / 2;
    },
    centerGroupH: function(obj) {
        obj.y = game.height / 2 - obj.height / 2;
    },
    centerGroupW: function(obj) {
        obj.x = game.width / 2 - obj.width / 2;
    },
    alignToBottom: function(obj, offset = 0) {
        obj.y = game.height - obj.height / 2;
        obj.y+= offset;
    },
    fromBottom: function(obj, percent, offset) {
        obj.y = game.height - (game.height * percent);
        obj.y -= offset;
    },
    fromTop:function(obj,percent,offet=0)
    {
    	obj.y=game.height*percent;
    	obj.y+=percent;
    },
    fromRight: function(obj, percent, offset = 0) {
        obj.x = game.width - (game.width * percent);
        obj.x -= offset;
        //obj.x -= obj.width / 2;
    },
    fromLeft: function(obj, percent, offset = 0) {
        obj.x = game.width * percent;
        obj.x += offset;
    },
    fromCenterH(obj, percent) {
        obj.x = game.width / 2 - (game.width * percent);
        obj.x -= obj.width / 2;
    },
    fromCenterV(obj, percent) {
        obj.x = game.width / 2 - (game.width * percent);
        obj.x -= obj.width / 2;
    }
}

There are some extra functions in there not used in the example, that I thought you might find useful. Play around with them ๐Ÿ™‚

Click here to open the result in a new tab. Then use the mobile testing on the developer console(press f-12) on Chrome to switch between different devices.

Now I am not saying that this will work for every single situation. That is why planning is crucial before you start coding your game! This method has worked well for me and I hope you find it useful.

6 thoughts on “How do I scale my game in Phaser?”

    1. Yes, I’ve done that for a long time. The problem is that if you are using assets that go off the screen such as a scrolling platform game, game.world.centerX is the center of the entire contents, not just the screen.

  1. Centering works for images, but for text, the first letter starts at the center and all the rest is push off to the right. How to fix it so the whole text is centered?

    1. You need to set the origin for your text to center. Text is left-top aligned by default.

      Default
      myTextObject.setOrigin(0,0);

      Centered
      myTextObj.setOrigin(0.5,0.5);

Leave a Comment