Box 2D 2.1a Tutorial – Part 5 (Collision filtering)

So the past couple of tutorials we have looked at collisions, in regards to detecting them per body, as well as detecting the exact points of collision. We will continue with the topic of collisions, but this time, we will be specifying filters so we can control which objects collide with which, rather than the default of all objects colliding.

In order to do this, we specify which objects can collide when we create the b2FixtureDef during the b2Body creation phase. The object property we will be dealing with is the b2FilterData property on the b2FixtureDef. There are two main ways for stating which b2Body objects should collide. The first we will look at is the groupIndex.

Group Index

The group index is of type Integer. We specify an integer which will be the identification of a group that the body belongs to. A b2Body that has had a positive groupIndex set will always collide with other bodies with the same number. If, instead, that b2Body had a negative groupIndex set, then it will never collide with other bodies of the same number. So a positive number  is a collision and a negative number is never a collision. Quite simple really.

While useful, what happens when we want multiple rules? For example, A has a negative index of -1, and so does B, as we don’t want them to collide. But then along comes C, who has a negative index of -2, but we also want to ensure that we don’t collide with it.

Category Bits and Mask Bits

This where category bits come in. The category bit is an unsigned integer (so only positive numbers). The difference here is we use the bits of the unsigned integer to represent categories. With an Interger being 16bit means we can specify 16 different categories. Also, unlike with the group index, a b2Body does not have to be part of just 1 group as we can set multiple bits to 1. Once we have specified the category that the body belongs to, then we then set another unsigned Integer, called the category mask, to specify which categories the b2Body will collide with and the wont collide with. A couple of points to take note of.

One important piece of information to note is that the collision pairing must be mutual. By that I mean, if body A has a mask that specifies that it collides with body B, then body B must have a mask that specifies it collides with A, otherwise they will not collide.

The other thing that I have noticed is that by default all bodies belong to category 1. So if you do not explicitly set the category mask, and another b2body has its mask set to 1, then they will collide.

Last, I should mention that the group index can be used in conjunction with category bits. Bear in mind that Group Indexes take precedence over whatever your category bits/masks specify.

So the code to perform filtering will look something like this:

//... other code related to creating the b2Body
var chainFixtureDef:b2FixtureDef = new b2FixtureDef();
chainFixtureDef.shape = chainShape;
chainFixtureDef.density = 1.0;
chainFixtureDef.friction = 0.1;
chainFixtureDef.filter.categoryBits = 4;
chainFixtureDef.filter.maskBits = 9;

_body.CreateFixture(chainFixtureDef);

At the top of the page I have created Box2D demo of a Jellyfish in the ocean and have set up a series of collision rules. There are a few ways I could have set this up, but in this implementation I have done the following.

  • The invisible walls have their categoryBits set to 0001 (1)
  • The bubbles have their categoryBits set to 0010 (2)
  • The Jellyfish head has the categoryBits set to 0100 (4)
  • The tentacles (including each segment) is set to 1000 (8)
  • Now I want the walls to collide with the Jellyfish head and Jellyfish tentacles. So it’s mask is set to
    0100 OR 1000 = 1100 = 12
  • The Jellyfish head I want to collide with the walls and with the tentacles so
    1000 OR 0001 = 1001 = 9

I then repeat this process so that tentacles collide with the Jellyfish head and walls.

Currently the bubbles collide with nothing, but let’s say that we wanted them to collide with the tentacles. We could follow a similar approach, and specify a mask (1000), so that it collides with the tentacles, and those tentacles collide with the wall, Jellyfish head, and bubbles (1110). Alternatively, we could set the GroupIndex property of the bubbles to 1 and set the GroupIndex property of the tentacles to 1 to achieve the same result.

So that’s about it for filtering. Just watch that binary math, easy to make a small mistake.

10 thoughts on “Box 2D 2.1a Tutorial – Part 5 (Collision filtering)

  1. kbsGameToilet says:

    why, you just SAVED MY SORRY ASS !

    Just couldn’t get my head round it till I read this – can’t believe how simple it is – i think the Jellyfish helped.

  2. Hi, Your tuts are great, when i have time i’ll translate them in french if your okay with that :).

    I’ve got a question : I’m testing possibilities of Box2D in order to create a basketball game.
    Is there a way to detect a collision between 2 objects without making them react ?

    In concrete terms, i want to use a static object to detect when then ball is in the basket, but it blocks the ball (cf. screenshot).
    If I exclude it from colliding, event isn’t triggered :/

    I’ve tried to change categoryBits dynamically in checkCollisions() but it didn’t work >.>

    currentBallObject.fixture.filter.categoryBits = 2;
    currentBallObject.fixture.filter.maskBits = 2;
    currentBallObject.body.CreateFixture(currentBallObject.fixture);

    Is there a way to dynamically change collisions’ category ? Or do you have any suggestions ?

    Thanks a lot ;)

  3. Anonymous says:

    Hi, thanks :) Yes, I would be fine if you wanted to translate them in French :)

    As for your question, you don’t need to worry about using filters. When you create the fixture set the isSensor property to true and that will do exactly what you want :)

  4. Maxime CHEVASSON says:

    I’ll test it on tuesday, thanks a lot ^^

    I’ll let you know if I found some time to translate it, the complete lack of documentation is a shame for such a powerful library.

    Once again, thanks for your works on your tuts, and for your answer ;)

  5. IsSensor works fine !

    Way to use it in the ContactListener function (not mentionned in your tuts) :

    if(contact.GetFixtureA().IsSensor())

    Cheers ;)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>