Как заставить мою стрелу остановиться, когда они столкнутся с целью? - PullRequest
1 голос
/ 08 октября 2019

Я создаю игру с JavaScript и инфраструктурой Phaser 3. Я отредактировал хитбокс своей цели, но когда стрела попадает, она просто падает с экрана. Как мне сделать стрелку, как это было бы в реальной жизни?

var physicsConfig = {
  default: 'arcade',
  arcade: {
    debug: false //CHANGE THIS TO TRUE TO SEE LINES
  }
}

var config = {
  type: Phaser.AUTO,
  width: 800,
  height: 600,
  physics: physicsConfig,
  scene: {
    preload: preload,
    create: create,
    update: update,
    render: render
  }
};

//Start the game
var game = new Phaser.Game(config);

function preload() {
  this.load.image('sky', 'assets/sky.png');
  this.load.spritesheet('archer', 'assets/archer_sprites.png', {
    frameWidth: 128,
    frameHeight: 128
  });
  this.load.image('target', 'assets/target.png');
  this.load.image('ground', 'assets/ground.png');
  this.load.image('rings', 'assets/rings.png');
  this.load.image('arrow', 'assets/arrow.png');
  this.load.audio('arrow_shot', 'assets/arrow_shooting.mp3');

}

function create() {
  //Load all the images
  this.add.image(400, 300, 'sky');
  this.add.image(200, 200, 'ground');
  this.add.image(300, 100, 'rings');
  //Create the archer/player
  this.player = this.physics.add.sprite(100, 410, 'archer');
  this.player.setBounce(0.2);
  this.player.setCollideWorldBounds(true);
  //Shooting animation
  this.anims.create({
    key: 'shoot',
    frames: this.anims.generateFrameNumbers('archer', {
      start: 0,
      end: 4
    }),
    frameRate: 20,
    repeat: 0
  });

  //Create the target
  this.target = this.physics.add.sprite(530, 365, 'target');
  this.target.setSize(115, 95).setOffset(70, 130); //TARGET HITBOX
  this.target.enableBody = true;
  this.target.setImmovable();
  //Create an array for arrows later
  this.arrows = [];
  //Get keypresses
  this.cursors = this.input.keyboard.createCursorKeys();
  //Assign input for spacebar
  this.spacebar = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE);
  //Play sound when the arrow is shot
  this.arrowSound = this.sound.add('arrow_shot');

}

function update() {
  //Declare constants for movement
  const playerMoveAmt = 200;
  const arrowMoveAmt = 1750;
  this.player.setDrag(2000);

  //Rotation of the player
  if (this.cursors.up.isDown && this.player.angle > -45) {
    this.player.angle -= 1;
  }
  if (this.cursors.down.isDown && this.player.angle < 0) {
    this.player.angle += 1;
  }

  //Shooting with the spacebar
  if (Phaser.Input.Keyboard.JustDown(this.spacebar)) {
    //Animate the shooting
    this.player.anims.play('shoot', true);
    //Arrow shooting
    var arrow = this.physics.add.sprite(this.player.x, (this.player.y + 20), 'arrow');
    arrow.enableBody = true;
    arrow.body.immovable = false;
    arrow.setGravityY(4000); //Gravity will affect the arrows
    arrow.angle = this.player.angle //Angle the arrows with the player
    arrow.setVelocityX(arrowMoveAmt);
    arrow.setVelocityY((this.player.angle * 50));
    this.arrows.push(arrow);
    this.arrowSound.play();
  }

}

function render() {}
body {
  margin: 0;
}
<script src="//cdn.jsdelivr.net/npm/phaser@3.11.0/dist/phaser.js"></script>

Я пытался сделать это без хитбокса и сделать скорость стрелки 0, как только она прошла x-значение цели, но мне нужно сделатьэто правильно, при столкновениях.

1 Ответ

2 голосов
/ 09 октября 2019

Я нашел решение для достижения желаемого поведения:

  • Сначала мы проверим, касался ли целевой спрайт слева.

  • Если условие оценивается как true, мы установим для стрелки спрайта значения силы тяжести и скорости значение 0;

Вы можете использовать этот фрагмент кода (он начинается после this.arrowSound.play()):

function update () {   
    //Declare constants for movement
    const playerMoveAmt = 200;
    const arrowMoveAmt = 1500;
    this.player.setDrag(2000); 

    //Move the player left or right
    if (this.cursors.right.isDown) 
    this.player.setVelocityX(playerMoveAmt);
    if (this.cursors.left.isDown)
    this.player.setVelocityX(-playerMoveAmt);

    //Rotation of the player
    if (this.cursors.up.isDown && this.player.angle > -45) {
        this.player.angle -= 1;}
    if (this.cursors.down.isDown && this.player.angle < 0) {
        this.player.angle += 1;}

    //Shooting with the spacebar
    if (Phaser.Input.Keyboard.JustDown(this.spacebar)) {
        //Animate the shooting
        this.player.anims.play('shoot', true);
        //Arrow shooting
        let arrow = this.physics.add.sprite(this.player.x, (this.player.y + 20), 'arrow');
        arrow.enableBody = true;
        arrow.body.immovable = false;
        arrow.setGravityY(4000);    //Gravity will affect the arrows
        arrow.angle = this.player.angle //Angle the arrows with the player
        arrow.setVelocityX(arrowMoveAmt);
        arrow.setVelocityY((this.player.angle * 50));
        this.arrows.push(arrow);
        this.arrowSound.play();
    } else if(this.target.body.touching.left) {

        var i;

        for (i = 0; i < this.arrows.length; i++) {
          newArrows = this.arrows[i];

          newArrows.setGravityY(0);
          newArrows.setVelocityX(0);
          newArrows.setVelocityY(0);
        } 
    }
}

Я бы также предложил вам уменьшить Размер хитбокса стрелкового спрайта , поэтому похоже, что он действительно поражает целевой спрайт . Вы можете проверить текущий размер хитбокса , установив debug: true примерно так:

var physicsConfig = {
    default: 'arcade',
    arcade: {
        debug: true
    }
}
...