如何用Phaser 3创建任何屏幕大小的响应性游戏?
我一直在寻找一种解决方案,使我的游戏能够完全响应使用Phaser 3的任何屏幕分辨率,例如:
此示例是使用构造2创建的,顺便说一句,实现此效果非常简单。
有人知道使用Phaser 3实现此目的的最佳方法是什么吗?
解决方案
通过研究,我找到了问题的解决方案:
关键是使用父场景来控制所有其他子场景,该场景将与设备的屏幕大小相同。它还会在屏幕大小更改时调整子场景的大小,但始终保持纵横比不变。HandlerScene.js
export default class Handler extends Phaser.Scene {
// Vars
sceneRunning = null
constructor() {
super('handler')
}
create() {
this.cameras.main.setBackgroundColor('#FFF')
this.launchScene('preload')
}
launchScene(scene, data) {
this.scene.launch(scene, data)
this.gameScene = this.scene.get(scene)
}
updateResize(scene) {
scene.scale.on('resize', this.resize, scene)
const scaleWidth = scene.scale.gameSize.width
const scaleHeight = scene.scale.gameSize.height
scene.parent = new Phaser.Structs.Size(scaleWidth, scaleHeight)
scene.sizer = new Phaser.Structs.Size(scene.width, scene.height, Phaser.Structs.Size.FIT, scene.parent)
scene.parent.setSize(scaleWidth, scaleHeight)
scene.sizer.setSize(scaleWidth, scaleHeight)
this.updateCamera(scene)
}
resize(gameSize) {
// 'this' means to the current scene that is running
if (!this.sceneStopped) {
const width = gameSize.width
const height = gameSize.height
this.parent.setSize(width, height)
this.sizer.setSize(width, height)
const camera = this.cameras.main
const scaleX = this.sizer.width / this.game.screenBaseSize.width
const scaleY = this.sizer.height / this.game.screenBaseSize.height
camera.setZoom(Math.max(scaleX, scaleY))
camera.centerOn(this.game.screenBaseSize.width / 2, this.game.screenBaseSize.height / 2)
}
}
updateCamera(scene) {
const camera = scene.cameras.main
const scaleX = scene.sizer.width / this.game.screenBaseSize.width
const scaleY = scene.sizer.height / this.game.screenBaseSize.height
camera.setZoom(Math.max(scaleX, scaleY))
camera.centerOn(this.game.screenBaseSize.width / 2, this.game.screenBaseSize.height / 2)
}
}
通过这种方式,我们可以在父场景中并行启动其他场景。
PreloadScene.js
export default class Preload extends Phaser.Scene {
handlerScene = null
sceneStopped = false
constructor() {
super({ key: 'preload' })
}
preload() {
// Images
this.load.image('logo', 'assets/images/logo.png')
this.width = this.game.screenBaseSize.width
this.height = this.game.screenBaseSize.height
this.handlerScene = this.scene.get('handler')
this.handlerScene.sceneRunning = 'preload'
this.sceneStopped = false
...
}
create() {
const { width, height } = this
// CONFIG SCENE
this.handlerScene.updateResize(this)
// CONFIG SCENE
// GAME OBJECTS
this.add.image(width / 2, height / 2, 'logo').setOrigin(.5)
// GAME OBJECTS
}
}
在子场景中,必须从每个场景的Create函数调用父场景的updateReize函数。
ConfigGame.js
import Handler from './scenes/handler.js'
import Preload from './scenes/preload.js'
// Aspect Ratio 16:9 - Portrait
const MAX_SIZE_WIDTH_SCREEN = 1920
const MAX_SIZE_HEIGHT_SCREEN = 1080
const MIN_SIZE_WIDTH_SCREEN = 270
const MIN_SIZE_HEIGHT_SCREEN = 480
const SIZE_WIDTH_SCREEN = 540
const SIZE_HEIGHT_SCREEN = 960
const config = {
type: Phaser.AUTO,
scale: {
mode: Phaser.Scale.RESIZE,
parent: 'game',
width: SIZE_WIDTH_SCREEN,
height: SIZE_HEIGHT_SCREEN,
min: {
width: MIN_SIZE_WIDTH_SCREEN,
height: MIN_SIZE_HEIGHT_SCREEN
},
max: {
width: MAX_SIZE_WIDTH_SCREEN,
height: MAX_SIZE_HEIGHT_SCREEN
}
},
dom: {
createContainer: true
},
scene: [Handler, Preload]
}
const game = new Phaser.Game(config)
// Global
game.screenBaseSize = {
maxWidth: MAX_SIZE_WIDTH_SCREEN,
maxHeight: MAX_SIZE_HEIGHT_SCREEN,
minWidth: MIN_SIZE_WIDTH_SCREEN,
minHeight: MIN_SIZE_HEIGHT_SCREEN,
width: SIZE_WIDTH_SCREEN,
height: SIZE_HEIGHT_SCREEN
}
模式:Phaser.Scale.RESIZE非常重要,也是屏幕大小的最大值和最小值。
Mi Complete Solution在此:
https://github.com/shimozurdo/mobile-game-base-phaser3
探索:
https://labs.phaser.io/edit.html?src=src/scalemanager/mobile%20game%20example.js
相关文章