In my scenario, i create a ship according to player's preferences. The ship consists of the flag and the hull.
An example view
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.
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.
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)
}
}
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)
- create a container
- add the images to the container
- create a physics body for the container
- set the size for the container (default size is width=0 height=0)
- 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