如何在Phaser 3中实现全屏相机响应式设计,适配多终端屏幕?
用Phaser 3实现全屏响应式聚焦+UI适配
针对你需要的「窗口/屏幕变化时相机占满屏幕、动态调整聚焦区域、UI同步适配」的效果,可通过以下步骤实现,完美适配手机、平板、桌面等多设备:
一、初始化游戏配置:定义基础尺寸与缩放规则
首先在游戏初始化时,指定基础设计尺寸(比如你常用的设计稿分辨率,例1920x1080),并配置缩放策略让画布自动适配屏幕:
const config = { type: Phaser.AUTO, width: 1920, // 基础设计宽度 height: 1080, // 基础设计高度 scale: { mode: Phaser.Scale.RESIZE, // 随屏幕/窗口尺寸自动调整画布 autoCenter: Phaser.Scale.CENTER_BOTH, // 游戏始终居中显示 min: { width: 800, height: 600 }, // 最小适配尺寸(可选) max: { width: 2560, height: 1440 } // 最大适配尺寸(可选) }, physics: { default: 'arcade', arcade: { gravity: { y: 300 } } }, scene: { preload, create, update } }; const game = new Phaser.Game(config);
二、相机适配:动态调整聚焦区域
核心思路是:游戏世界设置为比基础尺寸更大的范围,相机根据屏幕宽高比自动缩放,确保填满屏幕的同时,聚焦到核心区域(比如玩家位置或世界中心)。
1. 设置世界边界与相机
在create方法中初始化世界边界和相机,并监听屏幕尺寸变化事件:
function create() { // 设置游戏世界边界(范围大于基础尺寸,方便不同屏幕显示不同区域) this.physics.world.setBounds(0, 0, 3840, 2160); // 配置主相机:限制在世界范围内移动 const camera = this.cameras.main; camera.setBounds(0, 0, 3840, 2160); // 监听屏幕尺寸变化,触发适配逻辑 this.scale.on('resize', handleResize, this); // 初始执行一次适配 handleResize.call(this); // 示例:创建玩家(后续可替换成你的游戏对象) this.player = this.physics.add.sprite(1920, 1080, 'player'); }
2. 编写尺寸适配逻辑
实现handleResize函数,根据屏幕宽高比计算相机缩放比例,并调整聚焦位置:
function handleResize() { const camera = this.cameras.main; const screenWidth = this.scale.gameSize.width; const screenHeight = this.scale.gameSize.height; // 计算世界与屏幕的宽高比 const worldRatio = 3840 / 2160; const screenRatio = screenWidth / screenHeight; let zoom; if (screenRatio > worldRatio) { // 屏幕更宽:按世界高度缩放,显示更多左右区域 zoom = screenHeight / 2160; } else { // 屏幕更高:按世界宽度缩放,显示更多上下区域 zoom = screenWidth / 3840; } // 应用相机缩放,并聚焦到玩家位置(或世界中心) camera.setZoom(zoom); camera.centerOn(this.player.x, this.player.y); // 替换成你的核心聚焦点 // 同步更新UI updateUI(this, zoom); }
三、UI适配:保持相对位置与比例
UI元素需要随屏幕尺寸动态调整位置和大小,确保始终处于预期的屏幕相对位置:
1. 创建UI元素并设置锚点
在create中创建UI时,通过setOrigin定义锚点,方便后续定位:
function create() { // ...(之前的相机、玩家代码) // 创建分数文本:锚点设为右上角,方便定位到屏幕右上角 this.scoreText = this.add.text(0, 0, 'Score: 0', { fontSize: '64px', fill: '#fff' }); this.scoreText.setOrigin(1, 0); }
2. 编写UI更新逻辑
在updateUI函数中,根据相机缩放比例调整UI的位置和大小:
function updateUI(scene, zoom) { const baseMargin = 50; // 基础设计中UI距离边缘的像素值 // 定位分数文本到屏幕右上角,距离边缘的距离随缩放比例变化 scene.scoreText.setPosition( scene.scale.gameSize.width - (baseMargin * zoom), baseMargin * zoom ); // 文本字号同步缩放 scene.scoreText.setFontSize(64 * zoom); }
进阶:用容器统一管理UI
如果有多个UI元素,可将它们放入Container中,整体调整缩放和位置,简化适配逻辑:
function create() { // 创建UI容器 this.uiContainer = this.add.container(); // 添加UI元素到容器 this.scoreText = this.add.text(1920 - 50, 50, 'Score: 0', { fontSize: '64px', fill: '#fff' }); this.scoreText.setOrigin(1, 0); this.uiContainer.add(this.scoreText); // ...添加其他UI元素到容器 } function updateUI(scene, zoom) { // 容器整体缩放,内部元素位置基于基础设计尺寸即可 scene.uiContainer.setScale(zoom); }
四、多设备测试
- 浏览器端:直接调整窗口大小,观察相机和UI的适配效果
- 移动端:使用浏览器的设备模拟器(Chrome DevTools)切换不同设备型号测试
- 针对特殊场景(如竖屏手机),可在
handleResize中判断屏幕宽高比,单独调整相机聚焦区域:
function handleResize() { const screenRatio = this.scale.gameSize.width / this.scale.gameSize.height; const camera = this.cameras.main; // ...(之前的缩放计算代码) if (screenRatio < 1) { // 竖屏模式:调整相机聚焦到玩家上方,避免被UI遮挡 camera.centerOn(this.player.x, this.player.y - 150); } else { // 横屏模式:聚焦玩家中心 camera.centerOn(this.player.x, this.player.y); } }
内容的提问来源于stack exchange,提问作者Elias Trizotti de Mattos
相关产品推荐
相关产品推荐

