Home > other >  Phaser 3 - Check group collision with world bounds
Phaser 3 - Check group collision with world bounds

Time:01-02

In my scenario, i create a ship according to player's preferences. The ship consists of the flag and the hull.

An example view

enter image description here

PROBLEM-1

Ship is an Arcade.Group and i want to prevent this group from going outside the borders of the world.

create(){
  // Create a group for ship
  this.shipGroup = this.physics.add.group()

  // Add hull to shipGroup
  this.shipGroup.create(400, 500, "1021")

  // Add flag to shipGroup
  const mainFlag = this.shipGroup.create(400, 500, "FA1")
  mainFlag.setOrigin(0.5, 0.8)

  // Set collision property to true of every object in shipGroup
  this.shipGroup.children.each((item: any) =>
    item.setCollideWorldBounds(true)
  )
}

update(t: number, dt: number){
    if (this.cursor.up.isDown) {
      this.shipGroup.setVelocity(...)
    }
    else {
      this.shipGroup.setVelocity(0, 0)
    }
}

With this approach every object in group calculated seperately. After hitting the world boundary, the position of the objects is distorted.

enter image description here

PROBLEM-2

To avoid this i tried another approach. I add bounding box to group. Instead of check collision for every object, i will only check collision for bounding box.

enter image description here

create(){
  // Create a group for ship
  this.shipGroup = this.physics.add.group()

  // Add bounding box for shipGroup
  this.shipBox = this.shipGroup.create(400, 500, "bbox")
  this.shipBox.setCollideWorldBounds(true)
  this.shipBox.body.onWorldBounds = true

  // Add hull to shipGroup
  this.shipGroup.create(400, 500, "1021")

  // Add flag to shipGroup
  const mainFlag = this.shipGroup.create(400, 500, "FA1")
  mainFlag.setOrigin(0.5, 0.8)

  /*this.shipGroup.children.each((item: any) =>
    item.setCollideWorldBounds(true)
  )*/
}
update(t: number, dt: number){
    if (this.cursor.up.isDown && !this.shipBox.body.checkWorldBounds()) {
      this.shipGroup.setVelocity(...)
    }
    else {
      this.shipGroup.setVelocity(0, 0)
    }
}

The problem is enter image description here

How can i implement collision for group and world boundary?

P.S. : phaser version is 3.55.2

CodePudding user response:

There are many ways to solve this problem, I personally would just use one image (hull and flag combined) and just move it, and switch it with a different, when needed.

That said, if you want to use the seperate images, the easy way is to use a phaser container. (link to the documentation)

  1. create a container
  2. add the images to the container
  3. create a physics body for the container
  4. set the size for the container (default size is width=0 height=0)
  5. done

A short demo:

document.body.style = 'margin:0;';

var config = {
    type: Phaser.AUTO,
    width: 536,
    height: 183,
    physics: {
        default: 'arcade',
        arcade: {            
            gravity:{ y: 0 },
            debug: true
        }
    },
    scene: {
        create
    },
    banner: false
}; 

function create () {
    this.add.text(10,10, 'Ship swimming')
        .setScale(1.5)
        .setOrigin(0)
        .setStyle({fontStyle: 'bold', fontFamily: 'Arial'});

    let graphics  = this.make.graphics();
    graphics.fillStyle(0xffffff);
    graphics.fillRect(0, 0, 10, 40);
    graphics.generateTexture('ship', 10, 40);
    
    
    graphics.fillStyle(0xff0000);
    graphics.fillRect(0, 0, 30, 10);
    
    graphics.generateTexture('flag', 30, 10);
    
    let hull = this.add.image(0, 0, 'ship')
    let flag = this.add.image(0, -5, 'flag')
    
    this.ship = this.add.container(100, 80, [ hull, flag]);
    
    this.ship.setAngle(90)
    
    this.ship.setSize(40, 30)

    this.physics.world.enable(this.ship);

    this.ship.body.setVelocity(100, 0).setBounce(1, 1).setCollideWorldBounds(true);
}

new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/phaser.js"></script>

Info: this demo is based partly from this official example

  • Related