Games [XUI2D] To Collide or Not To Collide

Erel

Administrator
Staff member
Licensed User
SS-2018-09-12_11.31.28.png


The purpose of this example is to demonstrate the usage of mask bits and category bits properties.

Collision rules:

- Collisions happen between dynamic bodies and other bodies (including other dynamic bodies).
- The collisions actually happen between two fixtures of two bodies. Bodies can have multiple fixtures with different properties.
- If a fixture is set to be a sensor (is sensor property) then the collision will be detected but there will not be a physical collision.

Now for mask bits and category bits. The formal rule sounds a bit complicated so we will start with an example.
The default mask bits is 65535 (0xFFFF).
0xFFFF in base 2 is 1111 1111 1111 1111.
Category bits should be a power of 2. This means that it is a number with a single high (1) bit. The default value is 1.

If the same bit is high in both the mask bits and the category bits then we have a collision.

In our example the second ground body mask bits value is 0 = 0000 0000 0000 0000. This means that it will never collide with other bodies. It is better to set the mask bits to 0 than using a sensor unless you are actually interested in detecting the collision.

The third ground body mask bits value is 65529 = 0xFFFF - 4 - 2 = 1111 1111 1111 1001
This means that it will collide with all bodies except bodies with category bits of 2 (10) or 4 (100).

The formal rule is:
For a collision to happen: (FixtureA.MaskBits & FixtureB.CategoryBits) <> 0 AND (FixtureA.CategoryBits & FixtureB.MaskBits) <> 0.
& - bitwise and.

Note that you can change the filter bits at runtime:
B4X:
bw.Body.FirstFixture.SetFilterBits(0, 0)
The above code is from Mario example. When Mario is hit we want to let Mario fall out of the screen.

There are two ways to detect collisions:
1. Call Body.GetContactList to get the current contacts. In most cases you will want to pass True for the TouchingOnly parameter. The items in the list returned are B2Contact items.

2. Handle the world contact events: BeginContact, PreSolve, PostSolve and EndContact. Note that PreSolve and PostSolve are not called for sensors.
The events are a bit more complicated to handle but are more powerful as they allow you to modify the contact behavior and they also include more information about the contact. See the walking character example.
The world is "locked" during these events. Don't add or destroy anything during these events. You can use X2.AddFutureTask to run something after the events complete.
Nice tutorial about box2d collisions: http://www.iforce2d.net/b2dtut/collision-anatomy

The example is included in the examples pack: https://www.b4x.com/android/forum/threads/xui2d-example-pack.96454/
 
Last edited:

CaStar

Member
Licensed User
Thanks for this. Is it possible to make an item passing a bar from one side but not from the other?
 

Gunther

Active Member
Licensed User
Hello,

Here a small (= more easy) example in a World_PreSolve sub where it is checked 1) if 'ball' is in contact and 2) if it is with 'coin'
If so, then the contact is disabled - means they will not collide.

'ball' and 'coin' are X2BodyWrapper.

Your task is in the if ...then to check if the item you deal with is on the one or other side of the other item.
According to that check set the "Contact.IsEnabled = False" or not.
B4X:
Private Sub World_PreSolve (Contact As B2Contact, OldManifold As B2Manifold)
    '
    Dim bodies As X2BodiesFromContact = X2.GetBodiesFromContact(Contact, "ball")
    If bodies = Null Then Return ' noone is in contact with 'ball'
    '
    'yes, the ball has contacts
    If bodies.OtherBody.Name = "coin" Then ' but is it 'coin' ?
        'yes, therefore ignore the collision if the ball
        Contact.IsEnabled = False
    End If
   '
End Sub
 
Last edited:

Gunther

Active Member
Licensed User
True 100%, but the focus is on:
Your task is in the if ...then to check if the item you deal with is on the one or other side of the other item.
According to that check set the "Contact.IsEnabled = False" or not.
;)
 

developer_123

Member
Licensed User
Good day. I have reviewed Erel's example, but for my purpose I can't find the logic of what I need. I have an array of characters that I create as
Dim character (n) As CharacterClass
where n is the number of characters that can vary randomly each time the application is loaded (5, 10, 15 characters, etc...). It is necessary that my characters collide with other objects, but that the characters DO NOT collide with each other. To assign the respective category and mask bits to each character, in such a way that they do not collide with each other, I cannot understand what consecutive values I should assign in the creation code of my characters. Maybe I can't understand the collision rule indicated by EREL
"The formal rule is:
For a collision to happen: (FixtureA.MaskBits & FixtureB.CategoryBits) <> 0 AND (FixtureA.CategoryBits & FixtureB.MaskBits) <> 0.
& - bitwise and. "

I appreciate if there is a code example of the form: bw.Body.FirstFixture.SetFilterBits (categorybit, 65529), which allows me to avoid the collision between my n characters.

The truth is a bit complex to understand this and I have not been able to do it after several hours of work.
 

Gunther

Active Member
Licensed User
May be this tool helps you to derive exactly which body shall collide with whom:

 

developer_123

Member
Licensed User
May be this tool helps you to derive exactly which body shall collide with whom:

Gunther, the table is very interesting, actually that's what I had in mind, a similar setup. Although Erel's answer already worked for me, I am going to do tests with this collision filter, since your input helps me a lot for my new characters.
 
Top