如何在Phaser3中缩放TiledMap以填充Canvas可用空间
Tiled地图适配Canvas全屏的Phaser响应式解决方案
要让Tiled导出的地图占满Canvas全部空间并适配所有屏幕尺寸,你需要通过计算缩放比例并动态调整地图容器/相机缩放来实现,替代不存在的groundLayer.resizeWorld()方法。以下是具体修改方案:
关键修改步骤
1. 补充resize处理方法
在Scene1类中添加resize方法,用于窗口尺寸变化时重新计算缩放比例并更新:
resize(gameSize) { const { width, height } = gameSize; const mapWidth = this.map.widthInPixels; const mapHeight = this.map.heightInPixels; // 计算宽高缩放比例,取最大值保证填满屏幕 const scaleX = width / mapWidth; const scaleY = height / mapHeight; const scale = Math.max(scaleX, scaleY); // 统一缩放游戏容器(包含地图和所有元素) this.gameContainer.setScale(scale); // 更新物理世界和相机边界 this.physics.world.setBounds(0, 0, mapWidth * scale, mapHeight * scale); this.cameras.main.setBounds(0, 0, mapWidth * scale, mapHeight * scale); // 保持相机跟随玩家 if (this.player) { this.cameras.main.startFollow(this.player); } }
2. 初始化时设置全屏适配逻辑
修改create方法,缓存地图实例到类属性,创建统一容器管理所有游戏元素,并计算初始缩放:
create() { // 缓存地图实例,方便resize时调用 this.map = this.make.tilemap({ key: 'map' }); const tileset1 = this.map.addTilesetImage('objects', 'objects'); const tileset2 = this.map.addTilesetImage('img_3500', 'img_3500'); const groundLayer = this.map.createLayer('groundLayer', tileset2, 0, 0); const worldLayer = this.map.createLayer('worldLayer_1', tileset1); // 创建统一容器,管理地图和所有游戏元素 this.gameContainer = this.add.container(0, 0); this.gameContainer.add([groundLayer, worldLayer]); // 添加玩家元素到容器 this.player = this.add .sprite(32, 64, 'playerDown') .setScale(0.5) .setDepth(10); this.gameContainer.add(this.player); // 添加障碍物和目标点到容器(基于原始地图坐标) this.obst = this.add.sprite( this.map.widthInPixels / 2, 64 * 2, 'pond' ).setScale(0.5); this.gameContainer.add(this.obst); this.goal = this.add.sprite( this.map.widthInPixels - 64 * 2, 64 * 3, 'goal' ).setScale(2); this.gameContainer.add(this.goal); // 计算初始缩放比例并应用 const gameWidth = this.sys.game.config.width; const gameHeight = this.sys.game.config.height; const mapWidth = this.map.widthInPixels; const mapHeight = this.map.heightInPixels; const scaleX = gameWidth / mapWidth; const scaleY = gameHeight / mapHeight; const scale = Math.max(scaleX, scaleY); this.gameContainer.setScale(scale); // 设置相机和物理世界边界 const camera = this.cameras.main; camera.setBounds(0, 0, mapWidth * scale, mapHeight * scale); camera.startFollow(this.player); this.physics.world.setBounds(0, 0, mapWidth * scale, mapHeight * scale); // 监听窗口resize事件 this.scale.on('resize', this.resize, this); }
3. 优化Phaser配置
调整scale配置,确保Canvas自动适配父容器并居中显示:
const config = { type: Phaser.AUTO, parent: 'phaser-test', pixelArt: true, preserveDrawingBuffer: true, physics: { default: 'arcade', arcade: { gravity: { y: 0 }, debug: false, }, }, scene: [Scene1], audio: { disableWebAudio: true, }, scale: { mode: Phaser.Scale.RESIZE, parent: 'phaser-test', width: '100%', height: '100%', autoCenter: Phaser.Scale.CENTER_BOTH, }, };
核心逻辑说明
- 统一容器缩放:将地图图层和所有游戏元素放入同一个容器,通过缩放容器实现整体适配,避免单独调整每个元素的繁琐操作。
- 比例适配:取窗口与地图宽高比值的最大值,确保地图填满屏幕的同时保持原始宽高比,避免拉伸变形。
- 动态响应:监听窗口resize事件,实时更新缩放比例和边界,保证窗口尺寸变化时仍保持全屏适配效果。
内容的提问来源于stack exchange,提问作者Sai Darshan
相关产品推荐
相关产品推荐

