Games [XUI2D] To Collide or Not To Collide

Erel

Administrator
Staff member
Licensed User


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?
 

Erel

Administrator
Staff member
Licensed User
Is it possible to make an item passing a bar from one side but not from the other?
Yes. It is more complicated. You can see an example of it in the walking character example.



The important code is in World_PreSolve sub.
 

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:

Erel

Administrator
Staff member
Licensed User
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.
This case is simpler and can be solved using the mask bits demonstrated in the first post.
 

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.
;)
 
Top