Phaser 3:从 canvas 纹理更新 Sprite 对象
Phaser 3: Update Sprite object from canvas texture
我创建了 3 个 canvas 纹理:
this.textures1 = this.textures.createCanvas('canvastextures1', 450, 170)
this.textures2 = this.textures.createCanvas('canvastextures2', 410, 180)
this.textures3 = this.textures.createCanvas('canvastextures3', 400, 210)
this.land1 = this.textures.get(MAPOPTIONS.BASE1_NAME).getSourceImage()
this.land2 = this.textures.get(MAPOPTIONS.BASE2_NAME).getSourceImage()
this.land3 = this.textures.get(MAPOPTIONS.BASE3_NAME).getSourceImage()
this.textures1.draw(0, 0, this.land1)
this.textures2.draw(0, 0, this.land2)
this.textures3.draw(0, 0, this.land3)
this.textures1.context.globalCompositeOperation = 'destination-out'
this.textures2.context.globalCompositeOperation = 'destination-out'
this.textures3.context.globalCompositeOperation = 'destination-out'
然后我通过 class Phaser.Physics.Arcade.Sprite
向 3 个 Sprite 对象添加 3 canvas 纹理并为它们启用 Physic
。最后,我将它们按 Phaser.GameObjects.Group
分组
我在 groupSprite 中调用一个 overlap(groupSprite, object)
函数来 ERASE
canvas 纹理,当对象与组重叠时(子弹对着陆并创建一个洞)。
this.activeTextures = this.textures.get('canvastextures3')
this.activeTextures.context.beginPath()
this.activeTextures.context.arc(Math.floor(overlap2.x), Math.floor(overlap2.y), 50, 0, Math.PI * 2)
this.activeTextures.context.fill()
this.activeTextures.update()
问题是 Sprite 对象不会跟随 canvas 纹理更新。有人有什么想法吗?谢谢。
一个简单的解决方案是创建一个属性(对象)来存储每个纹理的canvas,texture-key作为key/id,并更新canvas 上的纹理,调用一个方法(在这个 demo-code 中是方法 demoHit
)。
它并不优雅,但可以工作并且很快。在下面的简短演示中,您可以看到它如何只针对一个纹理工作,但添加更多应该很容易。
演示代码:
// Minor formating for Whosebug
document.body.style = "display: flex;flex-direction: column;";
class FirstScene extends Phaser.Scene {
constructor() {
super('firstScene')
this.canvasCollection = {};
}
create(){
this.createTextures();
this.scene.start('secondScene')
}
createTextures(){
let helperGraphics = this.make.graphics({x:0, y: 0, add: false});
helperGraphics.fillStyle(0xff0000);
helperGraphics.fillRect(0, 0, 20, 20 );
helperGraphics.generateTexture('helper', 20, 20);
let img = this.textures.get('helper').getSourceImage()
this.textures1 = this.textures.createCanvas('canvastextures1', 20, 20)
this.textures1.draw(0, 0, img)
this.textures1.context.globalCompositeOperation = 'destination-out'
this.canvasCollection['canvastextures1'] = this.textures1
// add here more textures ...
}
demoHit(textureKey, pos){
let currentCanvas = this.canvasCollection[textureKey];
currentCanvas.context.beginPath()
currentCanvas.context.arc(pos.x, pos.y, 5, 0, Math.PI * 2, false)
currentCanvas.context.fill()
currentCanvas.update()
}
}
class SecondScene extends Phaser.Scene {
constructor() {
super('secondScene')
}
create(){
this.loadScene = this.scene.get('firstScene')
this.textureGroup = this.physics.add.group({
immovable: true,
allowGravity: false
});
this.textureGroup.add(this.add.image(100, 85, 'canvastextures1'))
// add here more textures ...
this.ball = this.add.rectangle(100, 0, 10, 10, 0xffffff)
this.physics.add.existing(this.ball)
this.physics.add.overlap(this.ball, this.textureGroup, this.overlap, null, this )
}
overlap(player, groupItem){
groupItem.setTint(0xcdcdcd)
let pos = {
x: (player.body.center.x - groupItem.body.x),
y: 0
}
this.loadScene.demoHit(groupItem.texture.key, pos)
player.destroy();
}
}
var config = {
type: Phaser.AUTO,
width: 536,
height: 163,
physics:{
default: 'arcade',
arcade:{ gravity:{y: 100} }
},
scene: [FirstScene, SecondScene]
};
new Phaser.Game(config);
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.min.js">
</script>
我创建了 3 个 canvas 纹理:
this.textures1 = this.textures.createCanvas('canvastextures1', 450, 170)
this.textures2 = this.textures.createCanvas('canvastextures2', 410, 180)
this.textures3 = this.textures.createCanvas('canvastextures3', 400, 210)
this.land1 = this.textures.get(MAPOPTIONS.BASE1_NAME).getSourceImage()
this.land2 = this.textures.get(MAPOPTIONS.BASE2_NAME).getSourceImage()
this.land3 = this.textures.get(MAPOPTIONS.BASE3_NAME).getSourceImage()
this.textures1.draw(0, 0, this.land1)
this.textures2.draw(0, 0, this.land2)
this.textures3.draw(0, 0, this.land3)
this.textures1.context.globalCompositeOperation = 'destination-out'
this.textures2.context.globalCompositeOperation = 'destination-out'
this.textures3.context.globalCompositeOperation = 'destination-out'
然后我通过 class Phaser.Physics.Arcade.Sprite
向 3 个 Sprite 对象添加 3 canvas 纹理并为它们启用 Physic
。最后,我将它们按 Phaser.GameObjects.Group
我在 groupSprite 中调用一个 overlap(groupSprite, object)
函数来 ERASE
canvas 纹理,当对象与组重叠时(子弹对着陆并创建一个洞)。
this.activeTextures = this.textures.get('canvastextures3')
this.activeTextures.context.beginPath()
this.activeTextures.context.arc(Math.floor(overlap2.x), Math.floor(overlap2.y), 50, 0, Math.PI * 2)
this.activeTextures.context.fill()
this.activeTextures.update()
问题是 Sprite 对象不会跟随 canvas 纹理更新。有人有什么想法吗?谢谢。
一个简单的解决方案是创建一个属性(对象)来存储每个纹理的canvas,texture-key作为key/id,并更新canvas 上的纹理,调用一个方法(在这个 demo-code 中是方法 demoHit
)。
它并不优雅,但可以工作并且很快。在下面的简短演示中,您可以看到它如何只针对一个纹理工作,但添加更多应该很容易。
演示代码:
// Minor formating for Whosebug
document.body.style = "display: flex;flex-direction: column;";
class FirstScene extends Phaser.Scene {
constructor() {
super('firstScene')
this.canvasCollection = {};
}
create(){
this.createTextures();
this.scene.start('secondScene')
}
createTextures(){
let helperGraphics = this.make.graphics({x:0, y: 0, add: false});
helperGraphics.fillStyle(0xff0000);
helperGraphics.fillRect(0, 0, 20, 20 );
helperGraphics.generateTexture('helper', 20, 20);
let img = this.textures.get('helper').getSourceImage()
this.textures1 = this.textures.createCanvas('canvastextures1', 20, 20)
this.textures1.draw(0, 0, img)
this.textures1.context.globalCompositeOperation = 'destination-out'
this.canvasCollection['canvastextures1'] = this.textures1
// add here more textures ...
}
demoHit(textureKey, pos){
let currentCanvas = this.canvasCollection[textureKey];
currentCanvas.context.beginPath()
currentCanvas.context.arc(pos.x, pos.y, 5, 0, Math.PI * 2, false)
currentCanvas.context.fill()
currentCanvas.update()
}
}
class SecondScene extends Phaser.Scene {
constructor() {
super('secondScene')
}
create(){
this.loadScene = this.scene.get('firstScene')
this.textureGroup = this.physics.add.group({
immovable: true,
allowGravity: false
});
this.textureGroup.add(this.add.image(100, 85, 'canvastextures1'))
// add here more textures ...
this.ball = this.add.rectangle(100, 0, 10, 10, 0xffffff)
this.physics.add.existing(this.ball)
this.physics.add.overlap(this.ball, this.textureGroup, this.overlap, null, this )
}
overlap(player, groupItem){
groupItem.setTint(0xcdcdcd)
let pos = {
x: (player.body.center.x - groupItem.body.x),
y: 0
}
this.loadScene.demoHit(groupItem.texture.key, pos)
player.destroy();
}
}
var config = {
type: Phaser.AUTO,
width: 536,
height: 163,
physics:{
default: 'arcade',
arcade:{ gravity:{y: 100} }
},
scene: [FirstScene, SecondScene]
};
new Phaser.Game(config);
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.min.js">
</script>