如何使用 Phaser 3 以模式和随机位置产生收藏品或拾取物

How to spawn collectables or pickups in patterns and at random positions using Phaser 3

我正在使用 Phaser 3 制作一个 2d 无尽的跑步者,我需要在随机位置以及不同的图案(例如菱形、方形、... 我真的没有太多代码,我不知道该怎么做。我很乐意以任何方式提供任何帮助。谢谢。

这取决于您的代码,但我会使用函数 Phaser.Math.Between 来生成随机 positions/numbers (link to the documentation).

这里有一个很简单的方法:

代码中:

  • 生成金币的时间间隔是随机的
    setTimeout(_ => this.loadCoins(coins), Phaser.Math.Between(2500, 3000));
  • 拾音器的位置是随机的
    let yCoord = Phaser.Math.Between(20, 180);
    let xCord = 400 + Phaser.Math.Between(0, 100);
  • 取件类型随机
    let coinType = Phaser.Math.Between(0, 2);
  • 和生成的硬币数量
    let coinsToSpawn = Phaser.Math.Between(1, 5);

class GameScene extends Phaser.Scene {
    constructor() {
      super({ key: 'GameScene' });
    }
    
    loadCoins(coins){
       let coin;
       
       // Generate random amount of coins each time
       let coinsToSpawn = Phaser.Math.Between(1, 5);
       
       for(let i = 0; i < coinsToSpawn; i++){
         
          // Get Random y position (x is always bigger than the scene width)
          let yCoord = Phaser.Math.Between(20, 180);
          let xCord = 400 + Phaser.Math.Between(0, 100);

          // Randomly generate types
          let coinType = Phaser.Math.Between(0, 2);
          
          switch(coinType){
            case 0:
              coin = this.add.rectangle(xCord, yCoord, 15, 15, 0xFFFF00);
              break;
            case 1:
              coin = this.add.circle(xCord, yCoord, 7, 0xFF0000);
              break;
            case 2:
              coin = this.add.star(xCord, yCoord, 5, 5, 15, 0x00FF00);
              break;
          }
       
            coin = this.physics.add.existing(coin);
            coins.add(coin);
        }  
        coins.setVelocityX(-100); 
        
        // Start next Coin loading randomly in 2.5 - 3 Seconds
        setTimeout(_ => this.loadCoins(coins), Phaser.Math.Between(2500, 3000)); 
    }
    
    create() {
       
        this.player = this.add.rectangle(200, 100, 20, 20, 0xffffff);
        this.physics.add.existing(this.player);

        //Add World Physics
        this.physics.world.setBounds(0, 0, 400, 200);
        this.player.body.setCollideWorldBounds(true);
        this.player.body.setImmovable(true);

        let coins = this.physics.add.group({immovable: true, allowGravity: false});
        
        
        this.loadCoins(coins);
        
        this.physics.add.collider(this.player, coins, 
          (player, coin) => { 
            coin.destroy();
        });
  }
}

const config = {
    type: Phaser.AUTO,
    width: 400,
    height: 200,
    scene: [ GameScene ],
    physics: {
       default: 'arcade',
    }
};

const game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>

更新(用硬币创建形状):

-> 查看 Phaser.Actions 命名空间 (like to the documentation) 中的一些很酷的内置函数。 喜欢 _(仅举几例)):

  • Phaser.Actions.PlaceOnCircle
  • Phaser.Actions.PlaceOnLine
  • Phaser.Actions.PlaceOnTriangle
  • ...

免责声明:这段代码不是最优的,只是为了证明这一点而创建的。

产卵更新:

旁注:

  1. 生成必须被触发,所以我使用 setInterval,但您可以使用事件、用户输入,或者只是在 update 函数中,或者 ...
  2. 组的清理和保存可以更好地处理,但这是一个演示。

class GameScene extends Phaser.Scene {
    constructor() {
        super({ key: 'GameScene' });

        //keep reference to the groups
        this.coinGroups = [];
    }
    
    spawnCoins(){

       let coins = this.physics.add.group({immovable: true, allowGravity: false});
        
       var circle = new Phaser.Geom.Circle(440, 80, 40);
       for(let i = 0; i < 10; i++){
            let coin = this.add.circle(0, 0, 8, 0xFFFF00);
            coin = this.physics.add.existing(coin);
            coins.add(coin);
        }  
        coins.setVelocityX(-100); 

        this.coinGroups.push(coins);
        
        Phaser.Actions.PlaceOnCircle(coins.getChildren(), circle);
    }
    
    create() {
        this.add.text(10,10,'Spawing every 2sec')
            .setColor('#ffffff');

        // Spawing ever 2 Sec
        setInterval( _ => {
            this.spawnCoins();
        }, 2000);
    }

    update(){
        // Minor Cleanup
        for(let group of this.coinGroups){
            group.getChildren().forEach(child => {
                if(child.x < 0){
                    group.remove(child, true, true);
                }
            });
        }
        this.coinGroups = this.coinGroups.filter(group => group.length > 0 );  
    }
}

const config = {
    type: Phaser.AUTO,
    width: 400,
    height: 200,
    scene: [ GameScene ],
    physics: {
       default: 'arcade',
    }
};

const game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>

迷你演示 matter.js:

class GameScene extends Phaser.Scene {
    constructor() {
        super({ key: 'GameScene' });
        //keep reference to the groups
        this.coinGroups = [];
    }
    
    spawnCoins(){

       // standart Phaser Group
       let coins = this.add.group();
        
       var circle = new Phaser.Geom.Circle(440, 80, 40);
       for(let i = 0; i < 10; i++){
            let coin = this.matter.add.image(50, 50, 'coin').setOrigin(.5);
            coin.setIgnoreGravity(true);
            coin.setVelocityX(-3); 
            coin.setFrictionAir(0);
            coins.add(coin);
        }  

        this.coinGroups.push(coins);
        
        Phaser.Actions.PlaceOnCircle(
            coins.getChildren(), circle);
    }
    
    create() {
         this.add.text(10, 10, 'Coins spawned every second')
         .setOrigin(0)
         .setColor('#ffffff');
         
         // Just creating a texture/image for matter
         let g = this.make.graphics({x: 0, y: 0, add: false});
         g.fillStyle(0xffff00);
         g.fillCircle(7, 7, 7);
         g.generateTexture('coin', 14, 14);
          
          setInterval( _ => this.spawnCoins(), 1000);
    }

    update(){
      // Clean Up       
        for(let group of this.coinGroups){
            group.getChildren().forEach(child => {
                if(child.x < 0){
                    group.remove(child, true, true);
                }
            });
        }
       
        this.coinGroups = this.coinGroups.filter(group => group.getChildren().length > 0);
    }
}

const config = {
    type: Phaser.AUTO,
    width: 400,
    height: 200,
    scene: [ GameScene ],
     physics: {
        default: 'matter'
    },
};

const game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>