Jump to content

Physics bug


Puflo
 Share

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();
}

 

Link to comment
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' });
}

 

Link to comment
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?

Link to comment
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.

 

Link to comment
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);
}

 

Link to comment
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 ...

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...