alessa

Collider in group does not work

Recommended Posts

Hello everybody, new Phaser3 user here!

I am trying to modify the Making your First Game tutorial in order to make a prototype of a similar game with online multiplayer capabilities. Everything works fine, however I cannot make the collision of the bombs physics group to work against the current player.

Some of my code:

Initialization in create()

this.bombs = this.physics.add.group();

this.physics.add.collider(this.bombs, this.platforms);
this.physics.add.collider(this.player, this.bombs, hitBomb, null, this);

hitBomb callback function

function hitBomb(player, bomb){
  console.log("Inside hitBomb")
  this.physics.pause();
  player.setTint(0x000000);
  player.anims.play('turn');
}

In this example, the collision with the platforms of the game work fine.

Next step, I get some information from the server side SocketIO about some characteristics of the bomb to create when an event is triggered (the self you see here comes from var self = this;)

this.socket.on('bombLocation', function (bombLocation) {
  console.log("bombLocation message received");
  var bomb = self.bombs.create(bombLocation.x, bombLocation.y, 'bomb');
  bomb.setBounce(1);
  bomb.setCollideWorldBounds(true);
  bomb.setVelocity(bombLocation.velocityX, bombLocation.velocityY);
  bomb.allowGravity = false;
});

The bomb is spawn like it should be, everything works just fine. However, the hitBomb function never gets called (I can't see the console message). 

Am I missing something?

Cheers!

Share this post


Link to post
Share on other sites

Ok, I don't understand why but now I got it working by moving the line 

this.physics.add.collider(this.player, this.bombs, hitBomb, null, this);

Inside the bombLocation socket function, like this:

this.socket.on('bombLocation', function (bombLocation) {
    console.log("bombLocation message received");
    var bomb = bombs.create(bombLocation.x, bombLocation.y, 'bomb');
    bomb.setBounce(1);
    bomb.setCollideWorldBounds(true);
    bomb.setVelocity(bombLocation.velocityX, bombLocation.velocityY);
    bomb.allowGravity = false;
    self.physics.add.collider(player, bombs, hitBomb, null, self);
  });

I really would like to understand why, anybody knows perhaps?

Share this post


Link to post
Share on other sites

Don't add the collider inside the socket function, or it will create a brand new collider ever time that function is called, which I'm pretty sure is not what you wanted.

Instead, try and get it working without using a Socket connection at all - do the bombs work locally? If so, I think it's likely just a scope issue.

Share this post


Link to post
Share on other sites

Well, I tried again to put the collider outside the socket, like this:

// Creating a group for all the bombs in the game
bombs = this.physics.add.group();

// Collisions between bombs and platforms
this.physics.add.collider(bombs, platforms);

// Checking the collision between player and bombs
this.physics.add.collider(player, bombs, hitBomb, null, self);

The weird thing is that this way, the collision between bombs and platforms works well. So I don't think it can be a scope issue... the hitBomb function is declared outside the create function, in the same file, so it shouldn't be an issue to call it right? What I mean is this structure:

 

let gameScene = new Phaser.Scene('Game');

let config = {
  type: Phaser.AUTO,
  width: 800,
  height: 600,
  physics: {
    default: 'arcade',
    arcade: {
      debug: false,
      gravity: { y: 300 }
    }
  },
  scene: gameScene
};

let game = new Phaser.Game(config);

var sensorValue;
var pressureText;
var player;
var star;
var platforms;
var bombs;
var gameOver;
var otherPlayers;
var blueScoreText;
var redScoreText;

gameScene.preload = function () {
  ...
}

gameScene.create = function () {
  ...
}

gameScene.update = function () {
  ...
}

hitBomb = function(player, bomb){
  console.log("Inside hitBomb");
};

I have also other functions at the same scope of hitBomb that get called without issues.

I tried a simplified version, releasing a bomb as soon as the game starts:

// Creating a group for all the bombs in the game
  bombs = this.physics.add.group();

  var bomb = bombs.create(200, 16, 'bomb');
  bomb.setBounce(1);
  bomb.setCollideWorldBounds(true);
  bomb.setVelocity(-200, 20);
  bomb.allowGravity = false;

  // Checking the collision between player and bombs
  this.physics.add.collider(player, bombs, hitBomb, null, self);

This also doesn't work :( I don't understand the issue honestly

Share this post


Link to post
Share on other sites

Just a crazy thought perhaps: could it be that the order in which you initialize the player and bombs affect whether the collider finds an instance of player or not? Is there a way to refresh this?

EDIT: I think I got this right! I tried to wrap the collider code into being initialized with a delay, like this:

// Wait 3 seconds to be sure that the player is created, so the collider can be associated with it
setTimeout(function () {
  // Checking the collision between player and bombs
  self.physics.add.collider(player, bombs, hitBomb, null, self);
}, 3000);

This actually works, but it's not the most elegant solution. Any suggestion? Perhaps a callback function when the player is created?

Share this post


Link to post
Share on other sites

I still don't really get why you can't create everything you need up-front, the moment the game starts. Create your bombs group, create the player, create the colliders. Then in the Socket callbacks all you need do is create the bombs themselves, within the pre-existing Group.

The fact you're having to use setTimeout is a big red warning flag there are structural problems in the code imho.

Share this post


Link to post
Share on other sites

The problem is that the player is created on the server, therefore I experienced that the collider needs to be created once both bombs and player are initialized. Since I have to wait information from the server to create the player, I have no other way than this unfortunately. However, instead of the timer I set up a callback function that is fired after a player is created. 

Share this post


Link to post
Share on other sites

I'm having the same issue, I can't get collisions to work with a group and my tilemap.

 

this.map = this.make.tilemap({ key: "map" });

    const tileset = this.map.addTilesetImage("warTileset_64x64", "tiles");

    this.belowLayer = this.map.createStaticLayer("Tile Layer 1", tileset, 0, 0);

    this.belowLayer.setCollisionByProperty({ collides: true });

    this.physics.world.setBounds(0, 0, this.map.widthInPixels, this.map.heightInPixels);

    this.playerBullets = this.physics.add.group({
      classType      : Bullet,
      runChildUpdate : true,
      setCollideWorldBounds: true,
    });

    this.physics.add.collider(this.belowLayer, this.playerBullets, () => {
      console.log('Collision')
    });

 

 

And this is my Bullet Class

 

import Phaser from 'phaser'

class Bullet extends Phaser.GameObjects.Sprite {
  constructor(scene) {
    super(scene, 0, 0, 'bullet');
    scene.physics.world.enable(this);
    scene.add.existing(this);
    this.speed = 1;
    this.born = 0;
    this.direction = 0;
    this.xSpeed = 0;
    this.ySpeed = 0;
    this.setSize(12, 12);
  }

  fire(shooter, target) {
    this.setPosition(shooter.x, shooter.y); // Initial position
    this.direction = Math.atan((target.x - this.x) / (target.y - this.y));

    // Calculate X and y velocity of bullet to moves it from shooter to target
    if (target.y >= this.y) {
      this.xSpeed = this.speed * Math.sin(this.direction);
      this.ySpeed = this.speed * Math.cos(this.direction);
    } else {
      this.xSpeed = -this.speed * Math.sin(this.direction);
      this.ySpeed = -this.speed * Math.cos(this.direction);
    }

    this.rotation = shooter.rotation; // angle bullet with shooters rotation
    this.born = 0; // Time since new bullet spawned
  }

  // Updates the position of the bullet each cycle
  update(time, delta) {
    this.x += this.xSpeed * delta;
    this.y += this.ySpeed * delta;
    this.born += delta;
    if (this.born > 1800) {
      this.setActive(false);
      this.setVisible(false);
    }
  }
}

export default Bullet;

 

 

The Bullets work locally, and they collide with the other players, but no with world bounds or tilemaps.

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.