设置游戏比例

Set game scale ratio

我试图让游戏适合屏幕,但我无法缩放舞台本身。使用像来自 CreateJS 的 EaselJS 这样的库,我可以简单地做 stage.scaleX = stage.scaleY = r.

在 Phaser 中,我不仅要扩展游戏,还要扩展 Phaser 外部的 HTML div(用于用户界面)。如您所见,无论我更改什么属性(game.scale.scaleModegame.scale.displayScale 等),绘制的矩形都不会根据当前屏幕大小进行缩放。有什么我可以做的吗?

const ProjectSettings = {
    backgroundColor: 0x333333,
    resolution: [100, 100],
};

const SceneContainers = {
    sceneContent: null,
    sceneCanvas: null,
    phaserGame: null,
    sceneUIDiv: null,

    init() {
        SceneContainers.sceneContent = document.getElementById('content');
        SceneContainers.phaserGame = new Phaser.Game({
            width: ProjectSettings.resolution[0],
            height: ProjectSettings.resolution[1],
            type: Phaser.AUTO,
            parent: SceneContainers.sceneContent,
            backgroundColor: ProjectSettings.backgroundColor,
            scene: [Preloader],
        });
        SceneContainers.sceneCanvas = SceneContainers.phaserGame.canvas;
        SceneContainers.sceneCanvas.classList.add('scene-canvas');

        SceneContainers.sceneUIDiv = document.createElement('div');
        SceneContainers.sceneUIDiv.id = 'scene-ui';
        SceneContainers.sceneContent.appendChild(SceneContainers.sceneUIDiv);
    },
};

const SceneScaler = {
    init() {
        SceneContainers.phaserGame.scale.scaleMode = Phaser.Scale.ScaleModes.RESIZE;
        SceneScaler.fitToScreen();
        window.addEventListener('resize', e => {
            SceneScaler.fitToScreen();
        });
    },

    fitToScreen() {
        const [contentW, contentH] = ProjectSettings.resolution;
        const [windowW, windowH] = [innerWidth, innerHeight];
        const ratio = contentW / contentH;
        const windowRatio = windowW / windowH;
        let scale = windowW / contentW;
        if (windowRatio > ratio) {
            scale = windowH / contentH;
        }

        //SceneContainers.sceneCanvas.width = contentW * scale;
        //SceneContainers.sceneCanvas.height = contentH * scale;
        SceneContainers.phaserGame.scale.resize(contentW * scale, contentH * scale);
        SceneContainers.sceneUIDiv.style.transform = `scale(${scale})`;
        SceneContainers.sceneContent.style.width = `${contentW * scale}px`;
        SceneContainers.sceneContent.style.height = `${contentH * scale}px`;
        SceneContainers.sceneUIDiv.style.width = `${contentW}px`;
        SceneContainers.sceneUIDiv.style.height = `${contentH}px`;
        SceneContainers.sceneContent.style.left =
        SceneContainers.sceneCanvas.style.left =
        SceneContainers.sceneUIDiv.style.left = `${windowW / 2 - (contentW * scale) / 2}px`;
        SceneContainers.sceneContent.style.top =
        SceneContainers.sceneCanvas.style.top =
        SceneContainers.sceneUIDiv.style.top = `${windowH / 2 - (contentH * scale) / 2}px`;
        //SceneContainers.phaserGame.scale.displayScale = new Phaser.Math.Vector2(scale, scale);
    },
};

class Scene extends Phaser.Scene {
    constructor(id) {
        super(id);
    }

    init() {
        this.events.on('shutdown', () => {
            SceneContainers.sceneUIDiv.innerHTML = '';
        });
    }
}

class Preloader extends Scene {
    constructor() {
        super('preloader');
    }

    preload() {
    }

    create() {
        this.add.rectangle(50, 50, 50, 50, 0xff6666);
    }
}

class EntryPoint {
    constructor() {
        this.init();
    }

    init() {
        SceneContainers.init();
        SceneScaler.init();
    }
}

new EntryPoint;
html, body {
    padding: 0;
    margin: 0;
    width: 100%;
    height: 100%;
}

html, body {
    background: #333333;
}

#content {
    position: absolute;
    display: inline-block;
}

.scene-canvas {
    position: absolute;
}

#scene-ui {
    display: inline-block;
    position: absolute;
    transform-origin: left top;
}
<script src="https://github.com/photonstorm/phaser/releases/download/v3.55.2/phaser.min.js"></script>
<div id="content"></div>

此外,出于某种原因,我的代码片段未定义 canvas.classList,所以如果有人可以解决这个问题,我将不胜感激。这个 classList 错误不会发生在我的项目中。

如果您只想自动缩放,可以使用配置参数 scale.mode 并将其设置为 Phaser.Scale.FIT,然后一切都应该缩放。

这里有一个非常简单的演示:
如果您调整 window 的大小(当您打开全尺寸片段并更改高度时),您应该会看到“缩放比例”

var Preloader = {
    create() {
        this.add.rectangle(50, 50, 50, 50, 0xff6666);
    }
};

new Phaser.Game({
    width:300,
    height:300,
    scale: {
        mode: Phaser.Scale.FIT,
    },
    type: Phaser.AUTO,
    scene: [Preloader],
});
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.min.js"></script>