'Phaser 3 - Groups of Dynamic Sprites Not Colliding
I can’t get two groups of dynamic sprites or a dynamic sprite and a group of dynamic sprites to collide. I can get each to collide with groups of static sprites that make up the level, but not the dynamic ones.
If I setup a collider for the sprites themselves instead of the group, they work fine. Not sure what’s going on.
Here is a link to my code. Could someone take a look?
https://github.com/deusprogrammer/mega-man-clone/blob/master/src/scripts/scenes/mainScene.ts
Solution 1:[1]
The reason why the collisions doesn't work, is the physics - body of the group of enemies, seems to be interfering with, physics objects of the objects inside of the group.
Just replace the line 19 this.enemyGroup = this.physics.add.group(); (from the linked file) mainScene.ts, with this line this.enemyGroup = this.add.group(); and the collisions should work.
That line will only create a "simple" phaser group, without a physics body.
Here a running demo:
(I stripped your code, down to only essentials)
class MegaMan extends Phaser.Physics.Arcade.Sprite {
constructor(scene, x, y) {
super(scene, x, y, 'megaman');
scene.add.existing(this);
scene.physics.add.existing(this);
this.bulletGroup = scene.physics.add.staticGroup();
this.scale *= 2;
this.body.setSize(22, 22);
this.setOrigin(0.5, 0.5);
this.setCollideWorldBounds(true).setInteractive();
this.controls = {
up: this.scene.input.keyboard.addKey('W'),
down: this.scene.input.keyboard.addKey('S'),
left: this.scene.input.keyboard.addKey('A'),
right: this.scene.input.keyboard.addKey('D'),
jump: this.scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE),
shoot: this.scene.input.keyboard.addKey('J')
};
}
update() {
super.update();
// Controls
if (this.controls.right.isDown) {
this.setVelocityX(150);
} else if (this.controls.left.isDown) {
this.setVelocityX(-150);
} else {
this.setVelocityX(0);
}
// If player is jumping
if (this.controls.jump.isDown && this.body.touching.down) {
this.setVelocityY(-400);
}
if (this.controls.shoot.isDown && !this.isShooting) {
this.isShooting = true;
let megaBusterShot = this.scene.physics.add.sprite(this.x + 32, this.y, 'wood1');
this.bulletGroup.add(megaBusterShot);
megaBusterShot.body.allowGravity = false;
megaBusterShot
.refreshBody()
.setVelocityX(this.flipX ? 300 : -300);
setTimeout(() => {
this.isShooting = false;
}, 200);
}
}
onHit() {
console.log("OUCH");
}
}
class MetHat extends Phaser.Physics.Arcade.Sprite {
constructor(scene, x, y) {
super(scene, x, y, 'methat');
scene.add.existing(this);
scene.physics.add.existing(this);
this.scale *= 1.5;
this.state = "idle";
this.setCollideWorldBounds(true);
this.setInteractive();
this.refreshBody();
}
onCollision() {
if (this.body.touching.left) {
this.body.velocity.x = 200;
} else if (this.body.touching.right) {
this.body.velocity.x = -200;
}
}
onHit(weapon) {
this.destroy();
}
update() {
if (this.scene.game.loop.frame % 500 === 0 && this.body.touching.down && this.state === 'idle') {
this.state = 'standing';
// Make him start walking shortly after standing up
setTimeout(() => {
this.state = 'walking';
this.setVelocityX(-200);
}, 200);
// Make him idle again after 10 seconds.
setTimeout(() => {
this.state = 'idle';
this.setVelocityX(0);
}, 3000);
}
}
}
let assetMap = {
"W1": {},
"W2": {},
"W3": {
name: "wood3",
file: "https://github.com/deusprogrammer/mega-man-clone/raw/master/src/assets/img/wood3.png",
},
"W4": {
name: "wood4",
file: "https://github.com/deusprogrammer/mega-man-clone/raw/master/src/assets/img/wood4.png",
},
}
const levels = {
level1: {
tilemap: [
["W3", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "W3"],
["W3", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "W3"],
["W3", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "W3"],
["W3", " ", " ", " ", " ", "W4", "W4", " ", " ", " ", " ", "W3"],
["W3", " ", " ", " ", " ", "W4", "W4", " ", " ", " ", " ", "W3"],
["W4", "W4", "W4", "W4", "W4", "W4", "W4", "W4", "W4", "W4", "W4", "W4"],
],
blocksX: 12,
blocksY: 6,
nextLevel: 'level2'
}
}
class Level extends Phaser.GameObjects.GameObject {
constructor(scene, levelConfig) {
super(scene, 'level');
this.levelConfig = levelConfig;
scene.add.existing(this);
scene.physics.add.existing(this);
this.blocks = this.scene.physics.add.staticGroup();
for (let y = 0; y < this.levelConfig.blocksY; y++) {
for (let x = 0; x < this.levelConfig.blocksX; x++) {
let asset = assetMap[this.levelConfig.tilemap[y][x]];
if (!asset) {
continue;
}
let block = scene.physics.add.staticSprite(x * 32, y * 32, 'floor');
block.scale *= 2;
block.setOrigin(0, 0)
.setPushable(false)
.setImmovable(true)
.setGravity(0)
.refreshBody();
this.blocks.add(block);
}
}
}
}
class MainScene extends Phaser.Scene {
constructor() {
super({ key: 'MainScene' });
}
preload(){
let graphics;
graphics = this.make.graphics({x: 0, y: 0});
graphics.fillStyle(0xffffff, 1);
graphics.fillRect(0, 0, 22, 22);
graphics.generateTexture('megaman', 22, 22);
graphics.fillStyle(0xff0000, 1);
graphics.fillRect(0, 0, 22, 22);
graphics.generateTexture('methat', 22, 22);
graphics.fillStyle(0xcdcdcd, 1);
graphics.fillRect(0, 0, 16, 16);
graphics.generateTexture('floor', 16, 16);
}
create() {
this.player = new MegaMan(this, 60, 0);
this.level = new Level(this, levels['level1']);
this.enemyGroup = this.add.group();
this.enemyGroup.add(new MetHat(this, 300, 0));
// Doesn't work? Why?
this.physics.add.collider(this.player, this.enemyGroup, () => {
this.player.onHit();
});
this.physics.add.collider(this.player.bulletGroup, this.enemyGroup, (megaBusterShot, obj2) => {
let enemy = obj2;
megaBusterShot.destroy();
enemy.onHit(megaBusterShot);
});
// Works
this.physics.add.collider(this.player.bulletGroup, this.level.blocks, (megaBusterShot) => {
megaBusterShot.destroy();
});
this.physics.add.collider(this.enemyGroup, this.level.blocks, (obj) => {
let enemy = obj;
enemy.onCollision();
});
this.physics.add.collider(this.player, this.level.blocks);
}
update() {
this.player.update();
this.enemyGroup.children.each((enemy) => {
enemy.update();
})
}
}
const config = {
type: Phaser.AUTO,
backgroundColor: '#0000000',
scene: [MainScene],
width: 400,
height: 248,
physics: {
default: 'arcade',
arcade: {
debug: true,
gravity: { y: 600 }
}
}
}
const game = new Phaser.Game(config)
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/phaser.js"></script>
I had a similar problem (https://stackoverflow.com/a/70944607/1679286), seems to be a problem with nesten Objects, that have physics bodies.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
