Sign in to follow this  
Puflo

Physics bug

Recommended Posts

Box2D always calls contact callback twice.

Here's an example: 185.50.68.103

Ship with collision category 2 (ship at left) calls contact callback once while ship with collision category 1 (default) calls it twice.

I've been trying to fix this for weeks but couldn't find any solution in web, i really need you guys to help me.

function create() {
    game.physics.startSystem(Phaser.Physics.BOX2D);

    game.stage.backgroundColor = '#2d2d2d';
	// User-controlled ship
	ship1 = game.add.sprite(250, 300, 'ship');
    game.physics.box2d.enable(ship1);
    ship1.body.setCircle(14);
	// Ship with collision category 2 (triggers contact callback only once, it shouldn't even trigger it)
	ship2 = game.add.sprite(200, 200, 'ship');
    game.physics.box2d.enable(ship2);
    ship2.body.setCircle(14);
	ship2.body.setCollisionCategory(2);
	// Ship with collision category 1 *default, i guess* (triggers contact callback TWICE)
	ship3 = game.add.sprite(300, 200, 'ship');
    game.physics.box2d.enable(ship3);
    ship3.body.setCircle(14);
	
    game.physics.box2d.setBoundsToWorld(true, true, true, true, false);
	
	ship1.body.setCategoryContactCallback(1, function(b1,b2,f1,f2,begin){
		if (begin){
			total += 1;
			hitText.text = 'Contact callback called '+total+' times';
			console.log("CONTACT: ", b2)
		}
	}, this);

    cursors = game.input.keyboard.createCursorKeys();
    game.add.text(5, 5, 'Use arrow keys to move.', { fill: '#ffffff', font: '14pt Arial' });
	
	total = 0;
    hitText = game.add.text(5, 30, 'Contact callback called 0 times', { fill: '#ffffff', font: '14pt Arial' });
}

function update() {

    if (cursors.left.isDown)
    {
        ship1.body.rotateLeft(300);
    }
    else if (cursors.right.isDown)
    {
        ship1.body.rotateRight(300);
    }
    else
    {
        ship1.body.setZeroRotation();
    }

    if (cursors.up.isDown)
    {
        ship1.body.thrust(300);
    }
    else if (cursors.down.isDown)
    {
        ship1.body.reverse(300);
    }

}

function render() {
    game.debug.box2dWorld();
}

 

Share this post


Link to post
Share on other sites

Hi, try to combine setCollisionCategory with setCollisionMask. By default mask is 0xFFFF  - collide with all other groups. Mask has to be set on both bodies (therefore setCollisionMask(1) on both ships). This works:

function create() {
    game.physics.startSystem(Phaser.Physics.BOX2D);

    game.stage.backgroundColor = '#2d2d2d';
	// User-controlled ship
	ship1 = game.add.sprite(250, 300, 'ship');
    game.physics.box2d.enable(ship1);
    ship1.body.setCircle(14);
    ship1.body.setCollisionCategory(1);
    //ship1.body.setCollisionMask(2 + 4);  // - will collide with ship2 (category 2) and ship3 (category 4) 
    ship1.body.setCollisionMask(4);        // - will collide only with ship2 (category 2)
    
	// Ship with collision category 2 (triggers contact callback only once)
	ship2 = game.add.sprite(200, 200, 'ship');
    game.physics.box2d.enable(ship2);
    ship2.body.setCircle(14);
	ship2.body.setCollisionCategory(2);
  ship2.body.setCollisionMask(1);
	// Ship with collision category 1 *default, i guess* (triggers contact callback TWICE)
	ship3 = game.add.sprite(300, 200, 'ship');
    game.physics.box2d.enable(ship3);
    ship3.body.setCircle(14);
    ship3.body.setCollisionCategory(4);
    ship3.body.setCollisionMask(1);
	
    game.physics.box2d.setBoundsToWorld(true, true, true, true, false);
	
	ship1.body.setCategoryContactCallback(1, function(b1,b2,f1,f2,begin){
		if (begin){
			total += 1;
			hitText.text = 'Contact callback called '+total+' times';
			console.log("CONTACT: ", b2)
		}
	}, this);

    cursors = game.input.keyboard.createCursorKeys();
    game.add.text(5, 5, 'Use arrow keys to move.', { fill: '#ffffff', font: '14pt Arial' });
	
	total = 0;
    hitText = game.add.text(5, 30, 'Contact callback called 0 times', { fill: '#ffffff', font: '14pt Arial' });
}

 

Share this post


Link to post
Share on other sites
3 hours ago, Tom Atom said:

Hi, try to combine setCollisionCategory with setCollisionMask. By default mask is 0xFFFF  - collide with all other groups. Mask has to be set on both bodies (therefore setCollisionMask(1) on both ships). This works:

// ship1.body.setCollisionMask(2 + 4); // - will collide with ship2 (category 2) and ship3 (category 4)

What exactly is 2 + 4 and why is collision mask 4 colliding with ship 2?

Share this post


Link to post
Share on other sites

First, sorry, this description was confusing:

ship1.body.setCollisionMask(4);        // - will collide only with ship2 (category 2)

should be:

ship1.body.setCollisionMask(4);        // - will collide only with ship3 (category 4)

What you are building in code is kind of collision grid like this:

Collisions.png.79747fb456532a47e67b821eb3fc94ae.png

Take row, assign category to your object - like category 1 for ship1 and determine what all other categories you want it collide with (columns for ship2 and ship3). Then set collisionMask to sum.

 

Share this post


Link to post
Share on other sites

I can't get ship2 and ship3 to collide world bounds, what i'm doing wrong?

They collide each other but only ship1 is colliding world bounds.

ship1 = game.add.sprite(200, 300, 'ship');
game.physics.box2d.enable(ship1);
ship1.body.setCircle(14);
ship1.body.setCollisionCategory(1);

ship2 = game.add.sprite(200, 200, 'ship');
game.physics.box2d.enable(ship2);
ship2.body.setCircle(14);
ship2.body.setCollisionCategory(2);
ship2.body.setCollisionMask(3);

ship3 = game.add.sprite(300, 200, 'ship');
game.physics.box2d.enable(ship3);
ship3.body.setCircle(14);
ship3.body.setCollisionCategory(2);
ship3.body.setCollisionMask(3);

game.physics.box2d.setBoundsToWorld(true, true, true, true, 1, 3); // or 2,3

Edit: I made a hotfix for this, but i'd like to know why is the example above isn't working.

game.physics.box2d.setBoundsToWorld(true, true, true, true);

for (var i in game.physics.box2d.walls){
    game.physics.box2d.walls[i].setCollisionCategory(2);
    game.physics.box2d.walls[i].setCollisionMask(3);
}

 

Share this post


Link to post
Share on other sites

- in original example, you are using setBoundsToWorld incorrectly. This is from source doc:

    /**
    * Sets the bounds of the Physics world to match the Game.World dimensions.
    * You can optionally set which 'walls' to create: left, right, top or bottom.
    *
    * @method Phaser.Physics#setBoundsToWorld
    * @param {boolean} [left=true] - If true will create the left bounds wall.
    * @param {boolean} [right=true] - If true will create the right bounds wall.
    * @param {boolean} [top=true] - If true will create the top bounds wall.
    * @param {boolean} [bottom=true] - If true will create the bottom bounds wall.
    * @param {number} [collisionCategory=1] - The category (bitmask) to use for the walls.
    * @param {number} [collisionMask=0xFFFFFFFF] - The mask (bitmask) to use for the walls.
    */
    setBoundsToWorld: function (left, right, top, bottom, collisionCategory, collisionMask) {

... it is again about category / mask. But you passed "false" as 5th parameter instead of category. See default values in code above.


- for ship1 you are setting category to 1 and leaving collisionMask to default (which is 0xFFFF) - it says: "hey, I am from category 1 and I am colliding with EVERY other category". Which means: collide with bounds (category 1), other player-like ships (category 1) and both enemy ships (category 2) and everything else in physics world and any other category that may appear later...
- for ship2 and ship3, you are setting category to 2 and mask to 3 (= 1+ 2). It says: "I am from cat. 2 and I am collidiong with category 2 and category 1) - ships will now collide with bounds (cat. 1), player ship (cat 1) and with each other (cat 2). It will not collide with asteroids, planets, etc. if they are category 4 or 8 or 16 or ...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.