我一直在寻找一种解决方案,能够使用Phaser 3让我的游戏完全适应任何屏幕分辨率,例如:
这个例子是用Construct 2制作的,顺便说一句,在那里做到这个效果非常简单。
有人知道实现这一目标的最佳方法是什么吗?
我一直在寻找一种解决方案,能够使用Phaser 3让我的游戏完全适应任何屏幕分辨率,例如:
这个例子是用Construct 2制作的,顺便说一句,在那里做到这个效果非常简单。
有人知道实现这一目标的最佳方法是什么吗?
经过研究,我找到了解决问题的方法:
关键是使用一个父场景来控制所有其他子场景,这个场景将与设备屏幕大小相同。当屏幕大小改变时,它也会调整子场景的大小,但始终保持纵横比。
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
}
}
updateResize
函数必须从每个场景的创建函数中调用。
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
}
mode: Phaser.Scale.RESIZE
非常重要,还有屏幕大小的最大值和最小值。