在 Phaser 中的玩家精灵位置创建子弹精灵,但精灵不会被创建/添加到游戏中

Creating A Bullet Sprite At Players Sprite Location In Phaser But The Sprite Wont Be Created / Added To The Game

这是一款猴子在平台上移动收集硬币的游戏。我想让猴子在按下向下箭头和向左箭头时射出香蕉。

我将如何创建子弹?

我有射击按键,它会根据按下的箭头调用 shootR 或 shootL。我需要的是创建射弹并让它向右或向左移动(不受重力影响)。我能得到一些帮助来创建这个射弹吗 var proj = projs.create(x, y, 'proj');不管用。我擅长用 js 编码,phaser 对我来说是新手,所以非常感谢帮助。

var config = {
  type: Phaser.AUTO,
  width: 1900,
  height: 1000,
  physics: {
    default: 'arcade',
    arcade: {
      gravity: { y: 300 },
      debug: false
    }
  },
  scene: {
    preload: preload,
    create: create,
    update: update
  }
};
var main = document.getElementById("startBtn")
var heading = document.getElementById("header")
var gameOver
var platforms;
var score = 0;
var scoreText;
var leafAm = 0
var leafText
var gunAm = 0
var ammoAm = 0
var ammoText
var monkeyType = "monkey"
var delay = 0


function start() {
  game = new Phaser.Game(config);
  main.innerHTML = ''
  heading.innerHTML += '<h1 class="header2" onclick="shop()"><u>Click To Access Shop</u></h1>'
}

function preload() {
  this.load.image('Background', 'assets/Background.jpg');
  this.load.image('ground', 'assets/platform.png');
  this.load.image('coin', 'assets/coin.png');
  this.load.image('redCoin', 'assets/redCoin.png');
  this.load.spritesheet('monkey', 'assets/monkey.png', { frameWidth: 600, frameHeight: 720 });
  this.load.spritesheet('proj', 'assets/bullet.png', { frameWidth: 200, frameHeight: 200 });
}

function create() {
  this.add.image(500, 275, 'Background').setScale(3);
  platforms = this.physics.add.staticGroup();
  platforms.create(200, 650, 'ground').setScale(0.15).refreshBody();
  platforms.create(600, 400, 'ground').setScale(0.15).refreshBody();
  platforms.create(1600, 650, 'ground').setScale(0.15).refreshBody();
  platforms.create(750, 100, 'ground').setScale(0.15).refreshBody();
  platforms.create(850, 750, 'ground').setScale(0.15).refreshBody();
  platforms.create(100, 950, 'ground').setScale(0.15).refreshBody();
  platforms.create(400, 950, 'ground').setScale(0.15).refreshBody();
  platforms.create(700, 950, 'ground').setScale(0.15).refreshBody();
  platforms.create(1000, 950, 'ground').setScale(0.15).refreshBody();
  platforms.create(1300, 950, 'ground').setScale(0.15).refreshBody();
  platforms.create(1600, 950, 'ground').setScale(0.15).refreshBody();
  platforms.create(1900, 950, 'ground').setScale(0.15).refreshBody();
  platforms.create(1800, 800, 'ground').setScale(0.15).refreshBody();
  platforms.create(250, 250, 'ground').setScale(0.15).refreshBody();
  platforms.create(1000, 500, 'ground').setScale(0.15).refreshBody();
  platforms.create(1150, 220, 'ground').setScale(0.15).refreshBody();
  player = this.physics.add.sprite(100, 450, 'monkey').setScale(0.075);
  this.physics.add.collider(player, platforms);
  player.setBounce(0.2);
  player.setCollideWorldBounds(true);
  this.anims.create({
    key: 'left',
    frames: this.anims.generateFrameNumbers('monkey', { start: 0, end: 3 }),
    frameRate: 10,
    repeat: -1
  });
  this.anims.create({
    key: 'turn',
    frames: [{ key: 'monkey', frame: 4 }],
    frameRate: 20
  });
  this.anims.create({
    key: 'right',
    frames: this.anims.generateFrameNumbers('monkey', { start: 5, end: 8 }),
    frameRate: 10,
    repeat: -1
  });
  this.anims.create({
    key: 'shoot',
    frames: this.anims.generateFrameNumbers('proj', { start: 0, end: 3 }),
    framerate: 15,
    repeat: -1
  })
  coins = this.physics.add.group({
    key: 'coin',
    repeat: 10,
    setXY: { x: 12, y: 0, stepX: 150 }
  });
  coins.children.iterate(function (child) {
    child.setBounceY(Phaser.Math.FloatBetween(0.4, 0.8));
    child.setScale(0.05)
  });
  this.physics.add.collider(coins, platforms);
  this.physics.add.overlap(player, coins, collectCoin, null, this);
  redCoins = this.physics.add.group();
  this.physics.add.collider(redCoins, platforms);
  this.physics.add.collider(player, redCoins, hitredCoin, null, this);
  projs = this.physics.add.group()
  this.physics.add.collider(projs, platforms)
  this.physics.add.collider(projs, redCoins, shootredCoin, null, this)
  scoreText = this.add.text(16, 16, 'Score: 0₴', { fontSize: '40px', fill: 'rgb(85, 1, 1)' });
  ammoText = this.add.text(16, 66, 'Ammo: 0', { fontSize: '40px', fill: 'rgb(85, 1, 1)' });
  leafText = this.add.text(16, 116, 'Shields: 0', { fontSize: '40px', fill: 'rgb(85, 1, 1)' });
}

function update() {
  cursors = this.input.keyboard.createCursorKeys();
  if (cursors.down.isDown && cursors.left.isDown && delay == 0) {
    shootL()
  } else if (cursors.down.isDown && cursors.right.isDown && delay == 0) {
    shootR()
  }
  if (cursors.left.isDown) {
    player.setVelocityX(-240);
    player.anims.play('left', true);
  }
  else if (cursors.right.isDown) {
    player.setVelocityX(240);
    player.anims.play('right', true);
  }
  else {
    player.setVelocityX(0);
    player.anims.play('turn');
  }
  if (cursors.up.isDown && player.body.touching.down) {
    player.setVelocityY(-330);
  }
}

function collectCoin(player, coin) {
  coin.disableBody(true, true);
  score += 1;
  scoreText.setText('Score: ' + score + '₴');
  if (coins.countActive(true) === 0) {
    coins.children.iterate(function (child) {
      child.enableBody(true, child.x, 0, true, true);
    });
    var x = Phaser.Math.Between(0, 800);
    var redCoin = redCoins.create(x, 16, 'redCoin').setScale(0.05);
    redCoin.setBounce(1);
    redCoin.setCollideWorldBounds(true);
    redCoin.setVelocity(Phaser.Math.Between(-300, 300), 20);
  }
}

function shootR(player, redCoin, proj) {
  var x = player.x
  var y = player.y
  
  var proj = projs.create(x, y, 'proj');

  // proj.setVelocityX(-240);
  // player.anims.play('shoot', true);
  ammoAm -= 1
  ammoText.setText('Ammo: ' + ammoAm + '');
  delay = 1
  this.time.delayedCall(3000, delayer, null, this);
}

function shootL(player, redCoin, proj) {
  var x = player.x
  var y = player.y

  var proj = projs.create(x, y, 'proj');

  ammoAm -= 1
  ammoText.setText('Ammo: ' + ammoAm + '');
  delay = 1
  this.time.delayedCall(3000, delayer, null, this);
}

function hitredCoin(player, redCoin) {
  if (leafAm > 0) {
    leafAm -= 1
    leafText.setText('Shields: ' + leafAm + '');
    redCoin.disableBody(true, true);
    var x = Phaser.Math.Between(0, 800);
    var redCoin = redCoins.create(x, 16, 'redCoin').setScale(0.05);
    redCoin.setBounce(1);
    redCoin.setCollideWorldBounds(true);
    redCoin.setVelocity(Phaser.Math.Between(-300, 300), 20);
  } else {
    this.physics.pause();
    player.setTint(0xff0000);
    player.anims.play('turn');
    gameOver = true;
    this.time.delayedCall(3000, restart, null, this);
  }
}

function shootredCoin(projs, redCoin) {
  redCoin.disableBody(true, true);
  projs.disableBody(true, true);
}

function restart() {
  score = 0
  var leafAm = 0
  var gunAm = 0
  var ammoAm = 0
  this.scene.stop();
  this.scene.start();
}

function shop() {
  main.innerHTML = `<button class="shopBackground"></button>`
  main.innerHTML += `<button class="shop1">Shop</button>`
  main.innerHTML += `<button class="shop2">Warning: Shop Fast, you can still die</button>`
  main.innerHTML += `<button class="shop3" onclick = "buy1()">Banana Gun...₴100.00<br>(Ability to shoot bananas)<br>click here to buy</button>`
  main.innerHTML += `<button class="shop4" onclick = "buy2()">Leaf Shield...₴30.00<br>(Protection from 1 hit)<br>click here to buy</button>`
  main.innerHTML += `<button class="shop5" onclick = "buy3()">Bananas...₴10.00<br>(Extra ammo, gun comes with 1)<br>click here to buy</button>`
  main.innerHTML += `<button class="shop6">₴ is score</button>`
  main.innerHTML += `<button class="shop7" onclick="main.innerHTML = ''">Back To Game</button>`
  main.innerHTML += `<img src="/assets/banana1.png" class="banana1">`
  main.innerHTML += `<img src="/assets/banana2.png" class="banana2">`
  main.innerHTML += `<img src="/assets/leaf.png" class="leaf">`
}

function buy1() {
  if (score > 99 && gunAm < 1) {
    gunAm += 1
    ammoAm += 1
    score -= 100
    scoreText.setText('Score: ' + score + '₴');
    alert("You have bought a gun \nClick the down arrow and either left or right to shoot\nShooting costs ammo but bullets detroy the red orbs\nEnjoy and good luck")
  } else if (gunAm > 0) {
    alert("You already have one")
  } else {
    alert("Not enough score")
  }
}

function buy2() {
  if (score > 29) {
    leafAm += 1
    score -= 30
    scoreText.setText('Score: ' + score + '₴');
    leafText.setText('Shields: ' + leafAm + '');
  } else {
    alert("Not enough score")
  }
}

function buy3() {
  if (score > 9) {
    ammoAm += 1
    score -= 10
    scoreText.setText('Score: ' + score + '₴');
    ammoText.setText('Ammo: ' + ammoAm + '');
    ;
  } else {
    alert("Not enough score")
  }
}

function delayer() {
  delay = 0
}

如有任何帮助或想法,我们将不胜感激。

还有一些 HTML 和 CSS 但这些部分不会影响它,或者至少它们不应该

这里有些东西要打开,

Btw.: usually on Whosebug you should only post the essential code: https://whosebug.com/help/minimal-reproducible-example this makes helping easy

但是回到你的问题:

  • 首先,函数shootRshootL不起作用,因为它们是用参数定义的,但没有传递。 所以 player 参数重载了全局 player 变量(顺便说一句,全局播放器变量永远不会用 varletconst)

函数定义:

    function shootR(player, redCoin, proj) 
    ...

正在调用的函数:

    ...
    if (cursors.down.isDown && cursors.left.isDown && delay == 0) {
        shootL()
    } else if (cursors.down.isDown && cursors.right.isDown && delay == 0) {
        shootR()
    }
    ...

快速修复: 传递播放器参数,示例:shootR(player)

  • 其次 shootRshootL 函数中的 this 没有指向正确的对象。

快速修复: 将场景传递给函数,示例:shootR(this, player) 并将函数更改为:

function shootL(scene, player,  redCoin, proj) {
    var x = player.x
    var y = player.y

    var proj = projs.create(x, y, 'proj');

    ammoAm -= 1
    ammoText.setText('Ammo: ' + ammoAm + '');
    delay = 1
    scene.time.delayedCall(3000, delayer, null, scene);
}
  • 第三个“去除重力”,只需使用
    快速修复: proj.body.setAllowGravity(false);shootRshootL (这里是 link to the documentation )函数中,

  • 最后只需添加子弹的速度proj.setVelocityX()

btw.: 可以使用 类 及其属性改进代码,我建议查看移相器示例 https://phaser.io/examples/v3/view/scenes/scene-from-class and/or https://phaser.io/examples/v3/view/scenes/scene-from-es6-class 关于如何使用 类 场景,这可以解决很多问题。而且您不需要使用全局变量或传递那么多参数。