phaserjs / phaser

Phaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.
https://phaser.io
MIT License
36.94k stars 7.08k forks source link

Canvas resizing problem in FIT mode #5702

Closed Matthieu-BRANTHOME closed 6 months ago

Matthieu-BRANTHOME commented 3 years ago

Version

Description

I have a scale problem on canvas:

phaserSmall phaserLarger phaserNormal

Example Test Code

// Configuration constants
const tileWidth = 128;
const nbTileGameWidth = 18;
const nbTileGameHeight = 7;
const gameWidth = nbTileGameWidth * tileWidth;
const gameHeight = nbTileGameHeight * tileWidth;
var config = {
    type: Phaser.AUTO,
    scale: {
        mode: Phaser.Scale.FIT,
        parent: 'phaser-game', // Attached DOM element
        width: gameWidth,
        height: gameHeight
    },
    physics: {
        default: 'arcade',
        arcade: {
            gravity: { y: 300 },
            debug: false
        }
    },
};
game = new Phaser.Game(config);
<!-- Bootstrap (styling) CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" 
        crossorigin="anonymous">
<!-- Boostrap library -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf"
        crossorigin="anonymous"></script>
<div class="container-fluid" style="height: 100vh">
    <div class="row h-100">
        <div class="col-4 bg-dark h-100 border-end border-2 d-flex flex-column" >
             Left menu...
        </div>
        <div class="col-8 h-100 d-flex flex-column">
           <div class="row border-bottom border-2">
                <div class="col p-0 m-0 bg-dark">
                    <div id="phaser-game"></div>
                </div>
            </div>
            <div class="row border-bottom border-2 bg-dark" style="height: 9%">
                <div class="col h-100  m-0 p-0">
                    <div class="row h-100 m-0 p-0">
                        <div class="col-2 h-100 m-0 p-0 d-flex align-items-center">
                            <div class="d-grid gap-2 col m-0 p-1 ">
                                <button id="runButton" onclick="runIt()" class="btn btn-success"
                                    type="button" disabled>Executer</button>
                            </div>
                        </div>
                        <div class="col-2 h-100 m-0 p-0 d-flex align-items-center">
                            <div class="d-grid gap-2 col m-0 p-1 ">
                                <button id="stopButton" onclick="stopIt()" class="btn btn-primary"
                                    type="button" disabled>Arrêter</button>
                            </div>
                        </div>
                        <div class="col-8 h-100 m-0 p-0 overflow-auto " id="alertContainer"></div>
                    </div>
                </div>
            </div>
            <div class="row overflow-auto bg-dark flex-grow-1" >
                <div class="col  m-0 p-0">
                    <div class="fs-6" id="codemirror-editor"></div>
                </div>
            </div>
        </div>
    </div>
</div>
halilcakar commented 3 years ago

Hello @Matthieu-BRANTHOME,

I also have similar problem with FIT mode and bootstrap. When you have a canvas in a blank page and resize you will see FIT mode is actually working perfect. When you start using bootstrap row col m-0 kinda classes I think the issue that parent container of Phaser can't actually resize cause bootstrap classes restrictions.

So I've created a small resize function to kinda make it happen and I've been using this since so long. Just give it a try.

// Hope u have jquery inside if you don't please change the selector and width(), height() methods :)
function resize(_game) {
    let canvas = _game.canvas;
    let par = $('.content');
    let windowWidth = par.width();
    let windowHeight = par.height();

    let gameRatio = _game.config.width / _game.config.height;
    canvas.style.width = windowWidth + 'px';
    canvas.style.height = (windowWidth / gameRatio) + 'px';
}

window.addEventListener('resize', () => resize(game));
Matthieu-BRANTHOME commented 3 years ago

Hello @halilcakar and thank you very much for this answer. I've done that :

function resize(_game) {
    var canvas = _game.canvas;
    var windowWidth = window.innerWidth;
    //var windowHeight = window.innerHeight;
    // let par = $('.content');
    // let windowWidth = par.width();
    // let windowHeight = par.height();

    var gameRatio = _game.config.width / _game.config.height;
    canvas.style.width = windowWidth + 'px';
    canvas.style.height = (windowWidth / gameRatio) + 'px';
}

window.addEventListener('resize', () => resize(game));

And it works! 👍

halilcakar commented 3 years ago

Hello @halilcakar and thank you very much for this answer. I've done that :

function resize(_game) {
    var canvas = _game.canvas;
    var windowWidth = window.innerWidth;
    //var windowHeight = window.innerHeight;
    // let par = $('.content');
    // let windowWidth = par.width();
    // let windowHeight = par.height();

    var gameRatio = _game.config.width / _game.config.height;
    canvas.style.width = windowWidth + 'px';
    canvas.style.height = (windowWidth / gameRatio) + 'px';
}

window.addEventListener('resize', () => resize(game));

And it works! 👍

Oh I'm glad it works for you :)

Please note that you need to remove the event listener if the page itself doesn't really reloads.

Matthieu-BRANTHOME commented 3 years ago

Please note that you need to remove the event listener if the page itself doesn't really reloads.

Sorry I'm not really understand: what does that mean?

halilcakar commented 3 years ago

Please note that you need to remove the event listener if the page itself doesn't really reloads.

Sorry I'm not really understand: what does that mean?

This is only needed if your application is SPA(Single Page Application). Meaning that you are using some kind of virtual router.

If you are using a virtual router then you should remove the event listener.

const res = () => resize(game);
window.addEventListener('resize', res);

// somewhere in your code before unload the page
window.removeEventListener('resize', res); // should appear so that next time you don't have get 2 resize listeners :)

Otherwise it's not needed.

Matthieu-BRANTHOME commented 3 years ago

Ok thanks, at the moment, i'm not using virtual router.