Phaser 3按Tailwind断点缩放GameObject时遇sudokuScene未定义报错
问题解决:Phaser 3 场景未加载报错及响应式尺寸调整
报错原因分析
- 创建
Phaser.Game后立即获取game.scene.keys.SudokuGameObjects,此时场景尚未完成初始化,导致sudokuScene为undefined。 - 原生
window.resize事件绑定时机过早,场景create方法未执行完成就调用resizeGameObject,触发错误。 create方法中this.box被重复赋值给文本对象,矩形对象引用丢失,后续setSize操作失效。- 获取屏幕宽度的方式错误:
canvas.style.width无法正确获取Tailwind设置的实际渲染宽度(w-full通过CSS继承生效,不会直接写入元素style属性)。
修复方案及代码调整
核心优化点
- 改用Phaser内置的Resize事件,确保场景初始化完成后再响应尺寸变化。
- 分开存储矩形和文本对象,避免引用覆盖。
- 使用Phaser自身的视口宽度匹配Tailwind断点规则,保证逻辑一致性。
修改后的主文件代码
import SudokuGameObjects from "./Classes/SudokuGameObjects"; const gameCanvas = document.createElement('canvas'); gameCanvas.id = 'gameCanvas'; gameCanvas.classList.add("w-full", "h-full", "mx-auto", "m-0"); const config = { type: Phaser.CANVAS, transparent: true, canvas: document.getElementById("gameCanvasContainer").appendChild(gameCanvas), scale: { zoom: 1, mode: Phaser.Scale.RESIZE, width: window.innerWidth, height: window.innerHeight }, scene: [SudokuGameObjects], physics: { default: 'arcade', arcade: { gravity: { y: 300 } } }, render: { pixelArt: false, roundPixels: true }, }; new Phaser.Game(config);
修改后的SudokuGameObjects文件代码
export default class SudokuGameObjects extends Phaser.Scene { constructor() { super({key: 'SudokuGameObjects', active: true}); this.rectBox = null; this.textBox = null; } resizeGameObject() { const viewportWidth = this.scale.width; // 匹配Tailwind断点:≥1536px用300x300,<1280px用150x150 if (viewportWidth >= 1536) { this.rectBox.setDisplaySize(300, 300); this.textBox.setFontSize(32); } else if (viewportWidth < 1280) { this.rectBox.setDisplaySize(150, 150); this.textBox.setFontSize(16); } // 可选:1280-1535px区间可自定义尺寸规则 } create() { // 创建矩形对象 this.rectBox = this.add.rectangle(300, 200, 100, 100, 0xff0000).setOrigin(0.5); this.rectBox.setDisplaySize(300, 300); // 创建文本对象,单独存储引用 this.textBox = this.add.text(300, 200, '1', { fontFamily: 'Figtree', fontSize: 32, color: '#ffffff', stroke: '#ffffff', strokeThickness: 1 }).setOrigin(0.5); // 绑定Phaser内置resize事件 this.scale.on('resize', () => { this.resizeGameObject(); }); // 页面加载时初始化一次尺寸 this.resizeGameObject(); } }
关键说明
- 用
this.scale.on('resize')替代原生window事件,确保场景完全初始化后再执行尺寸调整,彻底解决undefined报错。 this.scale.width直接获取Phaser视口宽度,和Tailwind的断点逻辑(xl=1280px,2xl=1536px)完全匹配。- 分开存储矩形和文本对象,避免引用覆盖导致的操作失效问题。
- 初始化时主动调用
resizeGameObject,保证页面加载完成就应用正确的尺寸。
内容的提问来源于stack exchange,提问作者summer9844
相关产品推荐
相关产品推荐

