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

发布于 2025-01-10 23:23:16 字数 5000 浏览 0 评论 0 原文

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

我的游戏应该是“Jetpack Joyride”的克隆,其中玩家跳跃以避开障碍物并收集硬币等。

我目前正在尝试创建一个通电装置,使屏幕上的所有硬币都向玩家变焦(因此收集所有硬币)的硬币)。

我使用了 this.physicals.moveToObject 函数,但它总是给我错误:“未捕获的类型错误:无法读取未定义的属性(读取“速度”)”。

我的想法是,这个函数不能一次提取多个对象 - 或者它不能“定位”“硬币”的所有实例(可能是因为我设置它们的随机生成的方式)。

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

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

无论如何,任何帮助都是值得赞赏的!

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);

    
    

})




}

Very new to Phaser so I think I might be fundamentally misunderstanding something.

My game is supposed to be a clone of 'Jetpack Joyride' where the player jumps to avoid obstacles and collect coins etc.

I am currently trying to create a powerup which makes all of the coins on screen zoom towards the player (and therefore collect all of the coins).

I have used the this.physics.moveToObject function but it always gives me the error: 'Uncaught TypeError: Cannot read properties of undefined (reading 'velocity')'.

My thinking is that this function can't pull multiple objects at once - or it isn't able to 'locate' all instances of 'coins'(perhaps because of the way I have set up the random generation of them).

This could also be something to do with a basic syntax error on my end.

One issue I have noticed is, I need to actually destroy the sprites as they go off the screen - but not sure this is related to the above.

Anyway, any help is appreciated!

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);

    
    

})




}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

雪化雨蝶 2025-01-17 23:23:16

好吧,导致错误的原因是您将 group 而不是 gameobject 传递给函数(详细信息可以在 文档)。
您可以循环遍历组中的所有子项/conis,对每个子项/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/[email protected]/dist/phaser.js"></script>

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

  • 仅拉特定距离内的硬币
  • 仅拉可见的硬币
  • 等等

Well the error is caused, because you are passing a group and not a gameobject to the function (details can befound in the documentation).
You could loop over all children/conis in the group, a call the function moveToObjecton each of them.

here a short demo (based on your code):

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/[email protected]/dist/phaser.js"></script>

Update:
I updated the code, so that "coins", that are behind the player won't be fulled. This can be tweeked to:

  • only pull coins in a specific distance
  • only pull coins that are visible
  • and so on
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文