【问题标题】:Phaser 3: Update Sprite object from canvas texturePhaser 3:从画布纹理更新 Sprite 对象
【发布时间】:2022-07-04 15:50:45
【问题描述】:

我创建了 3 个画布纹理:

    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'

然后我通过Phaser.Physics.Arcade.Sprite 类将 3 个画布纹理添加到 3 个 Sprite 对象,并为它们启用 Physic。最后,我将它们按Phaser.GameObjects.Group分组

当对象与组重叠时,我在 groupSprite 中调用overlap(groupSprite, object) 函数到ERASE 画布纹理(子弹与土地并创建一个洞)。

      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 对象不跟随画布纹理更新。有没有人有任何想法?谢谢。

【问题讨论】:

    标签: typescript sprite updates phaser-framework


    【解决方案1】:

    一个简单的解决方案是创建一个属性(对象)来存储每个纹理的画布,以纹理键作为键/id,并在画布上更新纹理,调用一个方法(在这个 demo-code就是方法demoHit)。

    它不是很优雅,但很有效。在下面的简短演示中,您可以看到它仅适用于一种纹理,但添加更多应该很容易。

    演示代码:

    // Minor formating for stackoverflow
    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>

    【讨论】:

    • 感谢winner_joiner 的精彩回复。但是它仍然没有更新 Sprite 对象,因为我还设置了 Sprite 对象的 body 大小让玩家可以在上面移动,我认为这会导致问题
    • @CSNo.1 感谢您的反馈。很抱歉我能帮上忙。我不太了解您的项目结构,但正如您提到的那样,额外的属性当然会导致副作用。
    • 谢谢,winner_joiner,Sprite 有两个维度:一个是我调用 this.textures.createCanvas('canvastextures1', 450, 170) 时的画布纹理,另一个是我调用 this.body 时的画布纹理.setSize(430, 50)(在 Phaser.Physics.Arcade.Sprite 类中扩展)
    猜你喜欢
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-18
    • 2015-06-08
    • 1970-01-01
    • 2019-01-02
    • 2019-01-26
    相关资源
    最近更新 更多