如何在Phaser 3中为容器创建遮罩以实现行星效果?
Phaser3 行星遮罩实现问题修正
你的代码里有几个核心问题导致遮罩后内容不显示:
- 遮罩Graphics不该加入容器:用来做
GeometryMask的Graphics是遮罩的数据源,不需要添加到容器的显示列表,加进去会打乱遮罩渲染逻辑,直接导致内容被隐藏。 - 层级顺序搞反了:阴影Sprite应该放在行星背景下面,现在的添加顺序会让阴影盖在行星上面;而且遮罩对象根本不需要参与渲染,别放进显示列表。
- 容器加遮罩容易出坐标问题:直接给容器设置遮罩很容易出现坐标偏移,不如给行星背景单独加遮罩,再组合到容器里更稳妥。
修正后的代码:
init({ x, y, size, sprite, id }) { const container = this.scene.add.container(x, y); const width = (1200 / 300) * 200; const height = 200; // 创建行星背景纹理并生成Sprite const earthBMD = this.scene.textures.createCanvas(`earthBMD${id}`, width, height); earthBMD.draw(0, 0, this.scene.textures.get(`map-${size}-${sprite}`).getSourceImage()); const planet = this.scene.add.sprite(0, 0, earthBMD).setOrigin(0.5).setAngle(-15); // 先加阴影到容器,确保层级在最底层 const shadow = this.scene.add.sprite(0, 0, 'sphere').setOrigin(0.5).setScale(0.5); container.add(shadow); // 创建遮罩用的Graphics(不加入任何显示列表) const maskGraphics = this.scene.make.graphics({ x: 0, y: 0 }); maskGraphics.fillStyle(0xffffff, 1); // GeometryMask只认形状,颜色透明度不影响,但要填充满 maskGraphics.fillCircle(0, 0, 150); // 转成纹理用BitmapMask更稳定,尤其容器有变换时 maskGraphics.generateTexture(`planetMask${id}`, 300, 300); // 给行星加遮罩,推荐用BitmapMask const maskTexture = this.scene.textures.get(`planetMask${id}`); const mask = new Phaser.Display.Masks.BitmapMask(this.scene, maskTexture); planet.mask = mask; // 把行星加到容器,层级在阴影上面 container.add(planet); return container; }
更靠谱的实现思路:
- 优先选BitmapMask:和GeometryMask比,BitmapMask在容器缩放、旋转时的坐标表现更稳定,不容易出现遮罩偏移或内容消失的问题。
- 固定层级顺序:阴影先加,行星后加,保证阴影在底层不会遮挡行星内容。
- 遮罩对象只做数据源:用来生成遮罩的Graphics或纹理,不需要添加到场景/容器的显示列表里,只作为遮罩的依赖资源即可。
内容的提问来源于stack exchange,提问作者biglebowsky19
相关产品推荐
相关产品推荐

