如何使所有某种类型的自动生成的精灵(在屏幕上 - 或存在)移动到 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
后面的“硬币”就不会被填满。这可以转发到:
- 只在特定距离拉币
- 只拉取可见的硬币
- 等等
对 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
后面的“硬币”就不会被填满。这可以转发到:
- 只在特定距离拉币
- 只拉取可见的硬币
- 等等