Bstrct
Bstrct

Reputation: 15

(Phaser 3 Arcade) Issue with collisions between 2 circular bodies

I instantiate a bunch of extended Phaser.Physics.Arcade.Sprite that move around the screen. When they hit each others, everything works has expected with the basic arcade body.

Although, It doesn't if I add "this.body.setCircle(200);" (or "this.setCircle(200);" btw, I'm not sure about the difference) in their constructor. Instead of smoothly deflecting on impact as I would have hoped, they stop immediately.

Here's the code of my class:

import Phaser from "phaser";

export default class Sheep extends Phaser.Physics.Arcade.Sprite {
  target: Phaser.Math.Vector2 = new Phaser.Math.Vector2();
  speed: number = 50;
  reach: boolean = true;

  constructor(scene: Phaser.Scene, x: number, y: number, spriteKey: string) {
    super(scene, x, y, spriteKey);
    this.setOrigin(0, 0);
    scene.physics.add.existing(this);
    scene.add.existing(this);
    this.setCircle(5);
    this.visible = false;
    //this.scale = 0.05;
    //this.setBounce(1);
  }
  setRandomTarget() {
    this.target = new Phaser.Math.Vector2(
      Math.random() * this.scene.scale.width,
      Math.random() * this.scene.scale.height
    );
  }
  preUpdate(time: number, delta: number) {
    super.preUpdate(delta, time);
    if (
      this.reach ||
      this.target.distance(new Phaser.Math.Vector2(this.x, this.y)) <=
        this.speed
    ) {
      this.setRandomTarget();
      this.reach = false;
      this.setHeading();
    }
  }
  setHeading() {
    let vPos = new Phaser.Math.Vector2(this.x, this.y);
    let vTarget = this.target.clone();
    let velocity = vTarget.subtract(vPos).normalize().scale(this.speed);
    this.setVelocity(velocity.x, velocity.y);
  }
}

Here's the code to create them and add them to the scene:

for (let i = 0; i < 10; i++) {
      this.sheeps.push(
        new Sheep(
          this,
          Math.round(Math.random() * width),
          Math.round(Math.random() * height),
          "sheep2"
        )
      );
    }
    let sheepGroup = this.physics.add.group(this.sheeps);

    this.physics.add.collider(sheepGroup, sheepGroup);

Here's the result: Circular collision Rectangular collision

Upvotes: 1

Views: 1118

Answers (1)

winner_joiner
winner_joiner

Reputation: 14730

Part one of your question
If you extend from Phaser.Physics.Arcade.Sprite in the constructor you can do both, this.setCircle (link documentation) or this.body.setCircle (link documentation) should do the same thing.

Part two of your question (look below for Update, solution)
Why it doesn't work, is difficult to say, without seeing your code, but here is how I would diagnose the problem:

  • turn on the debug setting for physics (I assume the collision box is somehow offset)

    var config = {
            ...
            physics: {
               default: 'arcade',
               arcade: {
                  ...
                  debug: true
               }
            },
      };
    
  • check the browser console for errors (immediate motion stop, indicates a probal error)

Update/Solution:
After going over your code, I would have to say the problem is the line
let sheepGroup = this.physics.add.group(this.sheeps);

just change it to

let sheepGroup = this.add.group(this.sheeps);

and it should work. The physics of the phaser group is interfering with the physics bodies of the sheeps.

Here the demo, I used for testing:

class Sheep extends Phaser.Physics.Arcade.Sprite {

  constructor(scene, x, y, spriteKey) {
    super(scene, x, y, spriteKey);
    this.target = new Phaser.Math.Vector2();
    this.speed = 50;
    this.reach = true;
    this.setOrigin(0, 0);
    scene.add.existing(this);
    scene.physics.add.existing(this);
    
    this.setCircle(5);
    this.visible = false;
    //this.scale = 0.05;
    this.setBounce(1);

  }
  setRandomTarget() {
    this.target = new Phaser.Math.Vector2(
      Math.random() * this.scene.scale.width,
      Math.random() * this.scene.scale.height
    );
  }
  preUpdate(time, delta) {
    super.preUpdate(delta, time);
    if (
      this.reach ||
      this.target.distance(new Phaser.Math.Vector2(this.x, this.y)) <=
        this.speed
    ) {
      this.setRandomTarget();
      this.reach = false;
      this.setHeading();
    }
  }

  setHeading() {
    let vPos = new Phaser.Math.Vector2(this.x, this.y);
    let vTarget = this.target.clone();
    let velocity = vTarget
        .subtract(vPos)
        .normalize()
        .scale(this.speed);

    this.setVelocity(velocity.x, velocity.y);
  }
}

var config = {
    type: Phaser.AUTO,
    width: 400,
    height: 200,
    physics: {
        default: 'arcade',
        arcade: {
            debug: true
        }
    },
    scene: { create }
};

var controls;

var game = new Phaser.Game(config);


function create ()
{
    this.sheeps = [];
  for (let i = 0; i < 20
  ; i++) {
      this.sheeps.push(
        new Sheep(
          this,
          Math.round(Math.random() * 400),
          Math.round(Math.random() * 200),
          "sheep2"
        )
      );
    }
    let sheepGroup = this.add.group(this.sheeps);

    this.physics.add.collider(sheepGroup, sheepGroup);
    
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/phaser.js"></script>

Upvotes: 1

Related Questions