0

I have a problem on Phaser3.

I developing a 2D platform game with Phaser3. And this game must be fit and playable on every mobile device with different resoulution.

My base game config is (I developing many games so I had wrote a base config for use on each game):

import Phaser, { Types } from "phaser";

const ratio = window.innerWidth < 600 ? 2 : 1;

const baseGameConfig: Types.Core.GameConfig = {
  type: Phaser.WEBGL,
  scale: {
    mode: Phaser.Scale.FIT,
    autoCenter: Phaser.Scale.CENTER_BOTH,
    width: window.innerWidth * ratio,
    height: window.innerHeight * ratio,
  },
  render: {
    antialias: true,
  },
};

export default baseGameConfig;

And my game config is:

import { Types } from "phaser";

import baseGameConfig from "@games/config.base";

import Scenes from "./src/scenes";

const gameConfig: Types.Core.GameConfig = {
  ...baseGameConfig,
  title: "platform2d",
  scene: Scenes.BootScene.scene,
  physics: {
    default: "arcade",
    arcade: {
      debug: process.env.NODE_ENV !== "production",
      gravity: {
        y: 600,
      },
    },
  },
};

export default gameConfig;

I using tilemaps, tilesets etc. in this game but I don't know how can I fit this tiles on the screen on every device. I research on internet but I didn't find any solution for this. All of them write the screen size like 800x600.

There is my tilemap as a json file:

{ "compressionlevel":-1,
 "height":20,
 "infinite":false,
 "layers":[
        {
         "data":[...],
         "height":20,
         "id":1,
         "name":"background",
         "opacity":1,
         "type":"tilelayer",
         "visible":true,
         "width":30,
         "x":0,
         "y":0
        }, 
        {
         "data":[...],
         "height":20,
         "id":2,
         "name":"wall",
         "opacity":1,
         "type":"tilelayer",
         "visible":true,
         "width":30,
         "x":0,
         "y":0
        }],
 "nextlayerid":3,
 "nextobjectid":1,
 "orientation":"orthogonal",
 "renderorder":"right-down",
 "tiledversion":"1.10.2",
 "tileheight":16,
 "tilesets":[
        {
         "columns":10,
         "firstgid":1,
         "image":"grass.png",
         "imageheight":128,
         "imagewidth":160,
         "margin":0,
         "name":"grass",
         "spacing":0,
         "tilecount":80,
         "tileheight":16,
         "tilewidth":16
        }, 
        {
         "columns":8,
         "firstgid":81,
         "image":"wall",
         "imageheight":128,
         "imagewidth":128,
         "margin":0,
         "name":"wall",
         "spacing":0,
         "tilecount":64,
         "tileheight":16,
         "tilewidth":16
        }],
 "tilewidth":16,
 "type":"map",
 "version":"1.10",
 "width":30
}

By the way I know I defined this tilemap a fixed width & height but like I said I don't know how can I do this in Phaser3.

There is a pictures of different resolution:

1

2

from my phone: my phone

I also used Phaser.Scale.RESIZE mode but when I used that mode, my assets' quality decreased because I must shrank scale of all assets otherwise they looked so big and overflow from screen.

I just want to scalable and same look this tiles, assets on every mobile device.

Thanks.

csgn
  • 21
  • 3

1 Answers1

0

The best solution would be to define the size of the game, center it and let phaser "stretch" it (with Phaser.Scale.FIT). Like this you will have on some devices a varying margin, but the look/display would be the same on all, and if you keep the background color/image (from the html page) in the same style of the game, it should look fit.

Something like this, where optimalGameWidth and optimalGameHeight would fit into the screen and/or the map size.

let config = {
    // these values are different as in the "scale" property
    width: optimalGameWidth,
    height: optimalGameHeight,
    scene: SampleScene,
    scale: {
        mode: Phaser.Scale.FIT,
        autoCenter: Phaser.Scale.CENTER_BOTH,
    },
}

Update:

Well the image has to be set on the body or other html - tag, not in the Phaser application. (Here you even could use css to change the image/image-size depeding on screensize or so, if you want to optimize more, and/or be more responsive)

And than you need to create a map that fits the new aspect ratio. In the following example I'm define a tilesize of 16px and a map size of width 16 tiles and height 9 tiles. You can use other sizes, but they should adhear to the aspect ratio of 16:9. (except if you want to scroll the map in game, than you can be more flexible. You can checkout official example for map scrolling, like this one)

A small demo:
(the background-image is grey)

class SampleScene extends Phaser.Scene {
  constructor(){
    super('SampleScene');
  }
  
  create () {
    this.add.text(10,10, 'This is the Game')
        .setScale(1.5)
        .setOrigin(0)
        .setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
        
    // Just to show that everything fits
    let border = this.add.rectangle(0, 0, config.width, config.height)
        .setOrigin(0);
        border.setStrokeStyle(5, 0xffffff);
  }

}

let tileSize = 16;
let aspectRatio = [16, 9];

let optimalGameWidth = aspectRatio[0] * tileSize;
let optimalGameHeight = aspectRatio[1] * tileSize;

var config = {
    width: optimalGameWidth,
    height: optimalGameHeight,
    scene: SampleScene,
    scale: {
        mode: Phaser.Scale.FIT,
        autoCenter: Phaser.Scale.CENTER_BOTH,
    },
}; 

new Phaser.Game(config);
html, body {
   margin: 0;
   padding: 0;
}

body {
  background-image: url('https://placehold.co/480x270/cdcdcd/FFFFFF.png?text=Background Background Background&font=montserrat');
  background-repeat: no-repeat;
  background-attachment: fixed; 
  background-size: 100% 100%;
}
<script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>

btw.: If you want to "fullscreen" the game/website you would have to use requestFullscreen on the wrapper html-tag. (In the case of the demo, you would be the body- tag. In code it would be something like this document.body.requestFullscreen();)

winner_joiner
  • 12,173
  • 4
  • 36
  • 61
  • What do you think is the optimal width or height? How can I define this? There are various devices available with different resolutions. – csgn Aug 30 '23 at 09:47
  • 1
    the optimal `width` and `height` has more to do with your asset and map size. You first need to know which resolutions / _aspect ratios_ you want to support (16:10, 16:9, ... ), than decide on a width / height ratio, that will fit all your devices well (some with margins) and create a map in that size(aspect ration). your current map is 3:2, it depends on how much you want to stretch the images and/or how much margin your are willing to accept per device. My Tipp would be build for one main device (aspect ratio), and for the rest accept minor differences. – winner_joiner Aug 30 '23 at 10:02
  • Okay, I will research and implement your advice. Thank you! – csgn Aug 30 '23 at 10:13
  • **btw.:** with your demo app you could simply use (480 x 320) since this is the size of your map. the map should be 100% on the screen. – winner_joiner Aug 30 '23 at 10:17
  • I added this tilemap for testing purposes. – csgn Aug 30 '23 at 10:26
  • Hello again. I chose to use a 16:9 aspect ratio to provide support but I didn't find any solution on how I could implement it on Phaser3. Could you share with me any source code, blog, etc. if you have any? And if I put any full-size background (as a PNG image) on the game and put the tiles (not the background layer) does this solve my problem? Thanks again. @winner_joiner – csgn Aug 31 '23 at 07:47
  • I updated my answer with a small demo, I hope this explains how to sovle this. – winner_joiner Aug 31 '23 at 08:35
  • Your demo did not solve my problem but: If I define some fixed sizes, like you said for different devices like: sm device = 100x100 md device = 500x500 lg device = 1000x1000 (values are just for example) And If I create some tilemaps like below: sm-tilemap.json (100x100) md-tilemap.json (500x500) lg-tilemap.json (1000x1000) If I detect the current device category (sm, md, or lg device), and load the tilemap (sm, md, or lg tilemap JSON) then the tilemap fits the device, right? What do you think about this approach? – csgn Aug 31 '23 at 11:05
  • The Demo shows what you have to do to display the same gamestate, no matter how big/small the device is. The width and height, are the same for all devices _(if you choose it to small it will look pretty bad, so pick the mid to large one)_, with the `scale` property `mode: Phaser.Scale.FIT,` **the canvas/game will be streched or shrunk to fit in the screen**. How big you make the map depends if the map should fit all on the screen or should be scrollable. if not scrollable the map size should be the same size of witdh/heigh of the config, if it should be scrollable, the map can be bigger. – winner_joiner Aug 31 '23 at 12:43