You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Phaser实现多设备多方向的游戏适配缩放?

Phaser 横竖屏适配优化方案

1. 优先用Phaser内置缩放模式替代手动计算

Phaser的ScaleManager自带类似Unity的自动适配能力,无需手动逐个调整元素。初始化游戏时配置好缩放规则,就能自动处理横竖屏切换的缩放与居中:

const gameConfig = {
  type: Phaser.AUTO,
  // 设定基准分辨率(示例为横屏1920x1080)
  width: 1920,
  height: 1080,
  scale: {
    // FIT模式:保持比例缩放,填满屏幕且不变形
    mode: Phaser.Scale.FIT,
    // 自动居中画布
    autoCenter: Phaser.Scale.CENTER_BOTH,
    // 限制最小/最大分辨率,避免极端尺寸下的显示异常
    min: { width: 960, height: 540 },
    max: { width: 3840, height: 2160 },
    // 防抖resize事件,避免频繁触发导致性能损耗
    resizeInterval: 100
  },
  scene: {
    preload: preload,
    create: create,
    // 仅当需要额外自定义逻辑时保留resize函数
    resize: resize
  }
};

new Phaser.Game(gameConfig);

2. 用容器(Container)批量管理元素

把关联元素(玩家、卡片、UI组件等)放进容器,只需调整容器的缩放和位置,就能批量控制所有子元素,彻底告别逐个设置的低效操作:

// 在create函数中初始化容器
create() {
  // 创建玩家容器并居中
  this.playerContainer = this.add.container(this.cameras.main.centerX, this.cameras.main.centerY);
  // 将所有玩家精灵添加到容器
  this.players.forEach(playerSprite => this.playerContainer.add(playerSprite));

  // 同理创建卡片容器
  this.cardContainer = this.add.container(this.cameras.main.centerX, this.cameras.main.height - 60);
  this.cards.forEach(cardSprite => this.cardContainer.add(cardSprite));
}

3. 优化resize函数,减少手动计算

利用Phaser内置的相机属性和缩放因子,替代window.innerWidth这类原生API,同时通过容器统一控制元素:

resize() {
  const camera = this.cameras.main;
  // Phaser自动计算的适配缩放比例
  const scaleFactor = this.scale.scaleFactor.x;

  this.stopTweening();

  // 背景图直接铺满相机视口
  this.bg.setDisplaySize(camera.width, camera.height);
  this.bg.setPosition(camera.centerX, camera.centerY);

  // 桌子容器居中并按比例缩放
  this.containerOfTable.setPosition(camera.centerX, camera.centerY);
  this.containerOfTable.setScale(scaleFactor);

  // 计时器与按钮基于相机视口定位
  this.timer.setScale(scaleFactor)
    .setPosition(this.table.getTopRight().x - 30 * scaleFactor, this.table.getTopRight().y + 20 * scaleFactor);

  this.button.setScale(scaleFactor)
    .setPosition(camera.width - 20 * scaleFactor, 30 * scaleFactor);

  // 批量更新玩家与卡片容器
  this.playerContainer.setScale(scaleFactor);
  this.playerContainer.setPosition(camera.centerX, camera.centerY);
  
  this.cardContainer.setScale(scaleFactor);
  this.cardContainer.setPosition(camera.centerX, camera.height - 60 * scaleFactor);

  this.tweenAs(this.cards[0], this.cards[2], this.cards[3]);
}

4. 横竖屏特殊布局处理

如果横竖屏需要不同的元素排列(比如玩家位置切换),可以通过this.scale.isPortrait判断,结合Phaser的对齐工具快速调整:

resize() {
  // ... 其他代码 ...

  const scaleFactor = this.scale.scaleFactor.x;
  const camera = this.cameras.main;

  if (this.scale.isPortrait) {
    // 竖屏:玩家垂直居中排列
    Phaser.Display.Align.To.AlignIn(this.playerContainer, camera, Phaser.Display.Align.CENTER, 0, 20 * scaleFactor);
    Phaser.Display.Align.To.VerticalCenter(this.playerContainer.getChildren(), 20 * scaleFactor);
  } else {
    // 横屏:玩家水平居中排列
    Phaser.Display.Align.To.AlignIn(this.playerContainer, camera, Phaser.Display.Align.CENTER, 20 * scaleFactor, 0);
    Phaser.Display.Align.To.HorizontalCenter(this.playerContainer.getChildren(), 20 * scaleFactor);
  }
}

关键注意事项

  • 避免直接使用window.innerWidth/Height,优先用this.cameras.main.width/height获取适配后的视口尺寸
  • 给resize事件加防抖,防止屏幕旋转时频繁触发导致的性能问题
  • 对于需要保持固定比例的元素,用Math.min(this.scale.scaleFactor.x, this.scale.scaleFactor.y)统一缩放,避免拉伸变形

内容的提问来源于stack exchange,提问作者a_7md.f

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 06:54:55