Using filters from Box2D in Libgdx
In a previous article, working with
Filters are processed before collision processing. That is, if at the filter level we specify that some objects do not collide, then there will be no collisions between these objects in the future. In the case of using
Categories and masks are the most powerful way to filter collisions, but also the most difficult (for beginners). The idea is to categorize the types of objects, and use masks to filter collisions between these types of objects. First, let's define categories.
Then set them to our objects.
You should have noticed that the numbering is 0 × 001, 0 × 002, 0 × 004, and 0 × 008. Why? The fact is that categories and masks are bit fields (encoded in 16 bits). This means that the possible categories are degree 2 (in decimal notation: 1, 2, 4, 8, 16, 32, 64, 128 ..., or in hexadecimal: 0 × 1, 0 × 2, 0 × 4, 0 × 8, 0 × 10, 0 × 20, 0 × 40, 0 × 80 ...). 16 bits mean that there are 16 possible categories from 0 × 0001 to 0 × 8000.
Now define the masks.
Ordinary Boolean algebra with typical operations on numbers. One has only to dwell on the mask and categories for landscape objects. Why is -1? -1 means that the object will be in contact with all other objects. If it is necessary that the object does not contact anyone, then set the value to 0.
Then we will set the masks to our objects.
If someone does not understand, pieces of code are presented by mask and category. I’ll give you the whole purpose of the filter just in case, as an example for a player:
As a result, the player will interact only with landscape objects and with Runner. Ballom with landscape only. Runner with player and landscape.
You can work with categories and masks, but sometimes there is no need to use them, count bit masks, etc. Groups were specially invented to disable / enable collision processing for some related objects.
To start, add another player.
In the class
It is also necessary to set groups for all other objects. Let the groupIndex platform be 3, and the blocks 2. In principle, the platform and blocks can not be assigned a group, then the default value will be set to 0. Now, if you start the game, the character will contact all objects except other characters.
You should have noticed that the index has a negative value. If the index is positive, the objects are always in contact; if it is negative, they are never in contact .
You can download the source from here .
ContactListener
. Here are just the examples that I used were not quite correctly selected. Box2D has much more convenient means for filtering collisions, namely filters. I’ll write about them this time. Filters are processed before collision processing. That is, if at the filter level we specify that some objects do not collide, then there will be no collisions between these objects in the future. In the case of using
ContactListener
, its methods for such objects will not work. Optimization on the face. Now let's take a closer look.Categories and masks
Categories and masks are the most powerful way to filter collisions, but also the most difficult (for beginners). The idea is to categorize the types of objects, and use masks to filter collisions between these types of objects. First, let's define categories.
// 0000000000000001 in binary
final public static short CATEGORY_PLAYER = 0x0001;
// 0000000000000010 in binary
final public static short CATEGORY_BALOOM = 0x0002;
// 0000000000000100 in binary
final public static short CATEGORY_RUNNER = 0x0004;
// 0000000000001000 in binary
final public static short CATEGORY_SCENERY = 0x0008;
Then set them to our objects.
//игроку
f.categoryBits = MyWorld.CATEGORY_PLAYER;
//блокам и платформе
f.categoryBits = MyWorld.CATEGORY_SCENERY;
//для Baloom'а
f.categoryBits = MyWorld.CATEGORY_BALOOM;
//для Runner'а
f.categoryBits = MyWorld.CATEGORY_RUNNER;
You should have noticed that the numbering is 0 × 001, 0 × 002, 0 × 004, and 0 × 008. Why? The fact is that categories and masks are bit fields (encoded in 16 bits). This means that the possible categories are degree 2 (in decimal notation: 1, 2, 4, 8, 16, 32, 64, 128 ..., or in hexadecimal: 0 × 1, 0 × 2, 0 × 4, 0 × 8, 0 × 10, 0 × 20, 0 × 40, 0 × 80 ...). 16 bits mean that there are 16 possible categories from 0 × 0001 to 0 × 8000.
Now define the masks.
final public static short MASK_PLAYER = CATEGORY_RUNNER | CATEGORY_SCENERY; // или ~MASK_PLAYER
final public static short MASK_BALOOM = CATEGORY_SCENERY ;
final public static short MASK_RUNNER = CATEGORY_PLAYER | CATEGORY_SCENERY ;
final public static short MASK_SCENERY = -1;
Ordinary Boolean algebra with typical operations on numbers. One has only to dwell on the mask and categories for landscape objects. Why is -1? -1 means that the object will be in contact with all other objects. If it is necessary that the object does not contact anyone, then set the value to 0.
Then we will set the masks to our objects.
//игроку
f.maskBits = MyWorld.MASK_PLAYER;
//блокам и платформе
f.maskBits = MyWorld.MASK_SCENERY;
//для Baloom'а
f.maskBits = MyWorld.MASK_BALOOM;
//для Runner'а
f.maskBits = MyWorld.MASK_RUNNER;
If someone does not understand, pieces of code are presented by mask and category. I’ll give you the whole purpose of the filter just in case, as an example for a player:
Filter f = new Filter();
f.categoryBits = MyWorld.CATEGORY_PLAYER;
f.maskBits = MyWorld.MASK_PLAYER;
playerSensorFixture.setFilterData(f);
playerPhysicsFixture.setFilterData(f);
As a result, the player will interact only with landscape objects and with Runner. Ballom with landscape only. Runner with player and landscape.
Group Filtering
You can work with categories and masks, but sometimes there is no need to use them, count bit masks, etc. Groups were specially invented to disable / enable collision processing for some related objects.
To start, add another player.
BodyDef def2 = new BodyDef();
def.type = BodyType.DynamicBody;
Body boxP2 = world.createBody(def2);
player2 = new Player(boxP2);
player2.getBody().setTransform(5.0f, 1.0f, 0);
player2.getBody().setFixedRotation(true);
In the class
Player
we define a group.Filter f = new Filter();
f.groupIndex = -1;
playerSensorFixture.setFilterData(f);
playerPhysicsFixture.setFilterData(f);
It is also necessary to set groups for all other objects. Let the groupIndex platform be 3, and the blocks 2. In principle, the platform and blocks can not be assigned a group, then the default value will be set to 0. Now, if you start the game, the character will contact all objects except other characters.
You should have noticed that the index has a negative value. If the index is positive, the objects are always in contact; if it is negative, they are never in contact .
Source code
You can download the source from here .