Phaser刮奖游戏重启问题:点击重玩按钮恢复遮盖层报错
解决Phaser刮奖游戏重玩功能失效与报错问题
问题核心分析
报错Cannot read properties of null (reading 'draw')的本质原因:
- 首次调用
createTexture时已创建coverTexture纹理,重玩时直接调用textures.createCanvas会因为同名纹理已存在,返回无效对象(或null),导致后续draw方法调用失败。 - 重玩时未清理旧游戏元素(遮盖层图片、底层图、百分比文本、定时器),造成元素堆积且状态混乱。
分步解决方案
1. 重玩前清理旧资源与状态
修改playAgainFct的点击回调,先彻底清理旧元素再重新初始化:
playAgain.on(Phaser.Input.Events.GAMEOBJECT_POINTER_DOWN, () => { // 清理定时器 if (this.checkTimer) { this.checkTimer.remove(); this.checkTimer = null; } // 销毁旧的刮奖相关元素 if (this.coverImageElement) this.coverImageElement.destroy(); if (this.skyImageElement) this.skyImageElement.destroy(); if (this.precent) this.precent.destroy(); // 移除旧的coverTexture纹理(解决draw方法报错的关键) if (this.textures.exists("coverTexture")) { this.textures.remove("coverTexture"); } // 重置刮奖状态 this.isPointerDown = false; // 清理粒子系统(如果有) this.destroyParticles(); // 重新初始化刮奖功能 this.createTexture(); this.scratchOff(); });
2. 保存元素引用以便清理
修改scratchOff方法,将创建的图片和文本保存为实例属性,方便后续销毁:
scratchOff() { this.precent = this.add.text(10, 10, ""); // 保存遮盖层图片引用 this.coverImageElement = this.add.image(this.screenCenter[0] - 171, this.screenCenter[1], "coverTexture") .setInteractive() .setScale(0.76) .setDepth(1); // 保存底层图片引用 this.skyImageElement = this.add.image(this.screenCenter[0] - 171, this.screenCenter[1], SKY_IMAGE) .setScale(0.76) .setDepth(0); // 绑定交互事件(移除原代码冗余的多层if判断) this.coverImageElement.on("pointerdown", this.startDrawing, this); this.coverImageElement.on("pointerup", this.stopDrawing, this); this.coverImageElement.on("pointermove", this.clearCover, this); this.checkTimer = this.time.addEvent({ delay: 250, loop: true, callback: this.checkPercent, callbackScope: this, }); }
3. 增强createTexture方法的鲁棒性
在创建新纹理前先移除旧纹理,确保每次都是全新初始化:
createTexture() { // 双重保险:先移除已存在的同名纹理 if (this.textures.exists("coverTexture")) { this.textures.remove("coverTexture"); } this.coverImage = this.textures.get(SKY_IMAGE_BLACK).getSourceImage(); this.coverHelperCanvas = this.textures.createCanvas("coverTexture", this.coverImage.width, this.coverImage.height); // 确保画布有效再执行后续操作 if (this.coverHelperCanvas) { this.coverHelperCanvas.draw(0, 0, this.coverImage); this.coverHelperCanvas.context.globalCompositeOperation = "destination-out"; this.canvasCollection = this.coverHelperCanvas; } }
额外注意事项
- 确保
SKY_IMAGE_BLACK和SKY_IMAGE纹理在游戏启动阶段已正确加载,避免getSourceImage()返回null。 - 如果有自定义粒子系统,需确保
destroyParticles()方法能彻底清理旧粒子实例。
内容的提问来源于stack exchange,提问作者georgio bejjani
相关产品推荐
相关产品推荐

