【问题标题】:How to spawn collectables or pickups in patterns and at random positions using Phaser 3如何使用 Phaser 3 在模式和随机位置生成收藏品或拾取物
【发布时间】:2022-06-11 16:33:04
【问题描述】:

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

【问题讨论】:

    标签: javascript phaser-framework


    【解决方案1】:

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

    旁注:第一个例子是为arcade物理制作的,最后一个是为ma​​tter.js制作的)

    这是一个非常简单的方法:

    在代码中:

    • 生成硬币的时间间隔是随机的
      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);
    &lt;script src="https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"&gt;&lt;/script&gt;

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

    -> 在 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);
    &lt;script src="https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"&gt;&lt;/script&gt;

    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);
    &lt;script src="https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"&gt;&lt;/script&gt;

    【讨论】:

    • 随机生成是可以的,但要使硬币在 x,y 点分别形成位置,形成锯齿形,菱形。我正在考虑创建硬币组,然后函数 Coin(x, y) { //运行精灵代码 Phaser.Sprite.call(this, scene, x, y, 'coin'); //向游戏中添加硬币 this.coinGroup.add(this);} coinshape ={} coinshape.zigzag= function(x,y){coin1 = new Coin(x,y) 并形成一个形状而我没有知道如何做这些我只是给一个建议@winner_joiner
    • 我一直在研究它,但有一个问题是它们可以在没有 setTimeout 的情况下连续生成,因为当超时调用函数时,它会破坏已经创建的函数,因此会循环。如果它与世界边界破坏相碰撞,我想要它,而且我还希望许多人在不考虑碰撞的情况下继续产卵。我希望你明白。感谢之前的回复。
    • @AceEnyioko 是的,setTimeout 仅用于展示概念。编写整个实际的生成脚本会更长/更复杂。我尽量用最少的代码来回答,以免混淆。我将更新第二个示例以生成 "better"
    • 这是一个非常好的方法和代码策略,我已经将我的代码与你的代码混合在一起,它可以工作。我有一个小问题,我的物质物理播放器没有与街机物理硬币发生碰撞。我知道这不是我的问题的一部分,但如果可以的话,请提供帮助。再次感谢。
    • @AceEnyioko 很好地混合物理引擎并不是最好的选择,如果它们发生碰撞的话。我个人会选择一个并使用该特定引擎做所有事情。最简单的方法是arcade,但matter应该也是可以的。
    猜你喜欢
    • 2022-10-08
    • 2011-02-24
    • 1970-01-01
    • 2020-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-06
    • 2018-03-31
    相关资源
    最近更新 更多