如何使所有某种类型的自动生成的精灵(在屏幕上 - 或存在)移动到 Phaser 上的定义点?

How do I make all of a certain type of automatically generated sprites (that are on screen - or exist) move to a defined point on Phaser?

对 Phaser 很陌生,所以我想我可能从根本上误解了一些东西。

我的游戏应该是 'Jetpack Joyride' 的克隆,玩家在其中跳跃以避开障碍物和收集金币等。

我目前正在尝试创建一个道具,使屏幕上的所有硬币都向玩家缩放(因此收集所有硬币)。

我使用了 this.physics.moveToObject 函数,但它总是给我错误:'Uncaught TypeError: Cannot read properties of undefined (reading 'velocity')'。

我的想法是这个函数不能一次拉取多个对象 - 或者它不能 'locate' 'coins' 的所有实例(可能是因为我设置的方式它们的随机生成)。

这也可能与我的基本语法错误有关。

我注意到的一个问题是,我需要在精灵离开屏幕时实际销毁它们 - 但不确定这是否与上述有关。

无论如何,我们将不胜感激!

const gameState = {
    score: 0,
    endGame: 0, 
    timer: 0,
    text1: '',
    text2: '',
    music:'',
    coinscore: 0,
    coincollect:'',
    speed: -400, 
    coins: '',
};


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



create() {

//Background 
this.createParalaxBackgrounds();

//Add Timer 
gameState.timer = this.time.addEvent({
    delay: 999999,
    paused: false
  });

//Add Player

var playerAnimation = this.anims.create({
    key: 'run',
    frames: [{
        key: 'player',
        frame: "sprite6"
    }, {
        key: 'player',
        frame: "sprite16"
    }],
    frameRate: 5,
    repeat: -1
  });

this.anims.create(playerAnimation);

this.player = this.physics.add.sprite(320, 300, 'Player').setScale(3).setDepth(11).play('run');
this.player.setSize(15, 16, false);

//Add Music

//gameState.music = this.sound.add('BackgroundMusic', { loop: true});
gameState.coincollect = this.sound.add('coin_collect', {loop : false});




//Add World Physics
this.physics.world.setBounds(0, 0, 800, 600);
this.player.setCollideWorldBounds(true);
this.player.setImmovable(true);

//Add Covid Physics
const covid = this.physics.add.group({immovable: true,
    allowGravity: false});
covid.setDepth(11);

gameState.coins = this.physics.add.group({immovable: true, allowGravity: false});
gameState.coins.setDepth(11);

const magnets = this.physics.add.group({immovable: true, allowGravity: false})
magnets.setDepth(11);



//Add Test Text
gameState.text1 = this.add.text(700, 10, `Score = ${gameState.score}`);
gameState.text1.setOrigin(0.5, 0.5).setDepth(11);
gameState.text2 = this.add.text(400, 50, `Coins Collected = ${gameState.coinscore}`, { fontSize: '15px', fill: '#000000' });
gameState.text2.setOrigin(0.5, 0.5).setDepth(11)

//Random Score Used for Coin Spawn Generation
const CoinNumb = 500;
//Random Score Used for Enemy Spawn Generation
const RandomCovidGenNumb = 2000;
//Random Scored used for Magnet
const MagnetSpawnNumb = 4000;
// Enemy Spawn
function CovidGen () {
    const yCoord = Math.random() * 600;
    covid.create(800, yCoord, 'Covid').setDepth(11);
    covid.setVelocityX(gameState.speed);

}

// Power Up Spawn 

function MagnetGen() {
    const yCoord = Math.random() * 600;
    magnets.create(800, yCoord, 'coin_magnet').setDepth(11);
    magnets.setVelocityX(gameState.speed);

}

// Adding Enemy Spawn Loop
const CovidGenLoop = this.time.addEvent({
    delay: RandomCovidGenNumb,
    callback: CovidGen,
    callbackScope: this,
    loop: true,
 });

// Adding Coin Spawn
function CoinGen () {
    const yCoord = Math.random() * 600;
    gameState.coins.create(800, yCoord, 'coin').setDepth(11).setScale(0.25);
    gameState.coins.setVelocityX(gameState.speed);

}

// Adding Coin Spawn Loop
const CoinGenLoop = this.time.addEvent({
    delay: CoinNumb,
    callback: CoinGen,
    callbackScope: this,
    loop: true,
 });

const MagnetGenLoop = this.time.addEvent({
    delay: MagnetSpawnNumb,
    callback: MagnetGen,
    callbackScope: this,
    loop: true,
 });


// Add Keyboard Input
const SpaceBar = this.input.keyboard.addKey('SPACE');



//Setting Enemy Spawn Velocity
//covid.setVelocityX(-300);



//Adding Collider between enemy and player + scene restart
this.physics.add.collider(this.player, covid, () => {
    gameState.score += gameState.coinscore;
    this.add.text(400, 300, `Game Over! \n Total Distance Travelled = ${gameState.score - gameState.coinscore} \n Total Coins Collected = ${gameState.coinscore} \n Total Score = ${gameState.score}`, { fontSize: '15px', fill: '#000000' }).setOrigin(0.5, 0.5).setDepth(11);
    CovidGenLoop.destroy();
    CoinGenLoop.destroy();
    this.physics.pause();
    gameState.timer.paused = true;
    gameState.endGame += 1;
    this.anims.pauseAll();
    
    this.input.on('pointerup', () => {
        gameState.endGame -= 1;
        this.scene.restart();
        gameState.timer.remove();
        gameState.coinscore = 0;
        this.anims.resumeAll();

    });
    
})

//Adding Collider between player and coin
this.physics.add.collider(this.player, gameState.coins, (player, coin) => { 
    coin.destroy();
    gameState.coinscore += 1;
    gameState.coincollect.play();
})

//Adding Collider between player and magnet power up

this.physics.add.collider(this.player, magnets, (player, magnet, coin) => { 
    magnet.destroy();
   
    this.physics.moveToObject(gameState.coins, this.player, 200);

    
    

})




}

嗯,错误是造成的,因为你传递的是 group 而不是 gameobject 给函数(细节可以在 documentation 中找到)。
您可以遍历组中的所有 children/conis,对每个 moveToObject 调用函数。

这里有一个简短的演示 (基于您的代码):

class GameScene extends Phaser.Scene {
    constructor() {
      super({ key: 'GameScene' });
    }
    
    loadCoins(coins){
    
        for(let i = 0; i < 5; i++){
            let yCoord = Math.random() * 200;
            let coin = this.add.rectangle(400, yCoord, 15, 15, 0xFFFF00);
            coin = this.physics.add.existing(coin);
            coins.add(coin);
        }  
        coins.setVelocityX(-100); 
    }
    
    create() {
        this.running = true;
        this.message = this.add.text(10, 10, 'Click to activate Magnet');
        
        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.input.on('pointerdown', _ => {
            if(this.running){
                coins.children.each(coin =>  {
                    // pull only coins infronz of the player
                    if(coin.x >= this.player.x){
                        this.physics.moveToObject(coin, this.player, 1500);
                    }
                });
                this.message.text = 'Click to reset';
            } else {
              this.loadCoins(coins);
              this.message.text = 'Click to activate Magnet';
            }
            this.running = !this.running;
        });
    
    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>

更新:
我更新了代码,这样 player 后面的“硬币”就不会被填满。这可以转发到:

  • 只在特定距离拉币
  • 只拉取可见的硬币
  • 等等