Phaser 3. 在运行时更改游戏尺寸

16

嗨,请帮我找出如何使用Phaser3创建真正响应式的游戏。

响应性很关键,因为游戏(Blockly工作区的表示层)应该能够在会话期间多次扩展到屏幕上的较大部分并缩小回来。

问题是我如何在运行时更改游戏的尺寸?

---编辑---

事实证明有纯CSS解决方案,可以使用CSS缩放属性来调整画布大小。在浏览器中运行良好(对性能没有明显影响),在cordova应用程序(Android)中也能正常运行。

如果CSS缩放可能会破坏某些东西,则Richard Davey的答案如下:

老实说,我从来没有尝试过。试一下看看会发生什么!它可能会破坏输入,或者它可能会继续工作。虽然它可能会破坏比例管理器,但除此之外,没有其他东西会受到太大关注。

// is size of html element size that needed to fit 
let props = { w: 1195, h: 612, elementId: 'myGame' };

// need to know game fixed size
let gameW = 1000, gameH = 750;

// detect zoom ratio from width or height
let isScaleWidth = gameW / gameH > props.w / props.h ? true : false;

// find zoom ratio
let zoom = isScaleWidth ? props.w / gameW : props.h / gameH;

// get DOM element, props.elementId is parent prop from Phaser game config
let el = document.getElementById(props.elementId);

// set css zoom of canvas element
el.style.zoom = zoom;
8个回答

7

您需要调整渲染器的大小,但还需要更新世界边界,以及可能是相机的边界。

// the x,y, width and height of the games world
// the true, true, true, true, is setting which side of the world bounding box
// to check for collisions

this.physics.world.setBounds(x, y, width, height, true, true, true, true);

// setting the camera bound will set where the camera can scroll to
// I use the 'main' camera here fro simplicity, use whichever camera you use

this.cameras.main.setBounds(0, 0, width, height);

这就是如何动态设置世界边界的方法。


6
window.addEventListener('resize', () => {
    game.resize(window.innerWidth, window.innerHeight);
});

1
如何调整游戏元素的大小? - Eddie
只需将物理世界的大小保持不变,无需调整。 - bFunc
3
在3.16.2中,game.resize不是一个函数,这就是我尝试时得到的结果。 - Gabriel
2
在3.22.0中使用game.scale.resize。 - Knekki

4

有一些内置的支持缩放的功能,可以在游戏配置中进行配置。查看ScaleManager选项。您可以根据您的需求在scale属性中指定许多选项。

我最终使用了以下内容:

 var config = {
            type: Phaser.AUTO,
            parent: 'game',
            width: 1280, // initial width that determines the scaled size
            height: 690,
            scale: {
                mode: Phaser.Scale.WIDTH_CONTROLS_HEIGHT ,
                autoCenter: Phaser.Scale.CENTER_BOTH
            },
            physics: {
                default: 'arcade',
                arcade: {
                    gravity: {y: 0, x: 0},
                    debug: true
                }
            },
            scene: {
                key: 'main',
                preload: preload,
                create: this.create,
                update: this.update
            },
            banner: false,
        };



3

如果其他人仍然遇到这个问题,我发现只调整游戏大小对我没有作用,并且在我的情况下物理效果也没有起作用。

为了使其工作,我需要调整游戏大小以及场景的视口(可以通过游戏的 scenemanager 属性获得场景):

game.resize(width,height)
scene.cameras.main.setViewport(0,0,width,height)

2

对于Phaser 3,游戏的resize现在与scale一起使用,如下所示:

window.addEventListener('resize', () => {
    game.scale.resize(window.innerWidth, window.innerHeight);
});

但如果您需要整个游戏的规模放大和缩小,只需要这个配置:
const gameConfig: Phaser.Types.Core.GameConfig = {
    ...
    scale: {
        mode: Phaser.Scale.WIDTH_CONTROLS_HEIGHT,
    },
    ...
};

export const game = new Phaser.Game(gameConfig);

mode: Phaser.Scale.WIDTH_CONTROLS_HEIGHT 对我很有帮助,用来替换 .FIT。使用 .FIT 后,画布会不稳定地重新缩放 3-4 次。 - ssstofff

0

看一下this文章。

它解释了如何在保持游戏比例的同时动态调整画布大小。

注意:以下所有代码均来自上述链接。我没有编写任何内容,它是从上述链接中获取的,但我在此发布它以防链接在将来失效。

它使用CSS来居中画布:

canvas{
    display:block;
    margin: 0;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

它监听窗口的“resize”事件并调用一个函数来调整游戏大小。
监听事件:
window.onload = function(){
    var gameConfig = {
       //config here
    };
    var game = new Phaser.Game(gameConfig);
    resize();
    window.addEventListener("resize", resize, false);
}

调整游戏大小:

function resize() {
    var canvas = document.querySelector("canvas");
    var windowWidth = window.innerWidth;
    var windowHeight = window.innerHeight;
    var windowRatio = windowWidth / windowHeight;
    var gameRatio = game.config.width / game.config.height;
    if(windowRatio < gameRatio){
        canvas.style.width = windowWidth + "px";
        canvas.style.height = (windowWidth / gameRatio) + "px";
    }
    else{
        canvas.style.width = (windowHeight * gameRatio) + "px";
        canvas.style.height = windowHeight + "px";
    }
}

我在我的Phaser 3项目中使用并修改了这段代码,它运行得非常好。

如果您想查看其他动态调整大小的方法,请单击此处


2
谢谢回复,但这并没有帮助,因为游戏物理引擎无法以那种方式感知画布大小的变化。看起来游戏实例中的某些属性也应该被更新。 - bFunc
这是我使用的另一个教程:https://www.emanueleferonato.com/2018/02/16/how-to-scale-your-html5-games-if-your-framework-does-not-feature-a-scale-manager-or-if-you-do-not-use-any-framework/。我认为它比我在答案中发布的更好,并且我正在将其用于我的当前项目中。 - Fabadiculous
1
Emanuele Feronato的文章在Phaser 3中确实有效。我已经使用过它,并且上面评论中链接的文章中也使用了Phaser 3。我将更新我的答案以使用那个更好的链接。 - Fabadiculous

0

将此代码放入您的创建函数中:

  const resize = ()=>{
    game.scale.resize(window.innerWidth, window.innerHeight)
  }
        
    window.addEventListener("resize", resize, false);

重要提示!请确保您拥有Phaser 3.16或更高版本,否则此操作将无法正常工作!!!

-4
使用game.resize函数:
// when the page is loaded, create our game instance
window.onload = () => {
    var game = new Game(config);

    game.resize(400,700);
};

请注意,这仅更改画布大小,不会影响其他任何内容。

这会创建一个新游戏?! - Totty.js
这并不能解决问题,因为在onload之后可能会发生调整大小。 - Sombriks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接