2

Is it possible to explain how bitmasking works for just this simplistic situation:

 A big (blue) ball.    Contact BitMask 0b0001

 A medium (red) ball.  Contact BitMask 0b0010

 A small (white) ball. Contact BitMask 0b0100

They have no collisions between them, because somehow this is turned off between them. I assume by setting their collision masks to 00 all the way through the 32 bits... but let's leave that for another question, I haven't yet figured out how to turn these off.

Having set each ball to have a unique contact bit mask, what is done that gives contact information when they contact?

How is it possible to know which two balls have contacted each other?

Is it possible to have the contact information only received by the biggest ball in any given contact?


UPDATE:

I'm not necessarily after code. If you need code to explain what's what, how it works, and why whatever does what, go for it.

But what I'm really after is an understanding of how bitmasking works to provide logic that permits the determination of "who" was involved in any contact.

The reason I've given each ball size a different bitmask is that I thought this might help determine the bigger ball in any given contact between two balls. I could be wrong about this, though.

UPDATE 2:

Understanding of processes progressing:

As I understand it, these are the parts of the process:

  1. Register SKView subclassed SKScene as conforming to the physics world contact notification delegate. Say it is so, too.

  2. Set bitmask as categories for each type of bodily interaction type desire to be known about and/or controlled in the simulation

  3. Use these bitmasks to articulate the nature of each object desired to be a part of contacts and/or collisions by applying them appropriately (some magic decision making in here).

  4. Override the contacts callback with code that does stuff, in the same SKView subclass registered as the delegate

  5. Create some magic code that determines who/what has contacted whom.


I understand some of these, but not the differentials of setting contact bitmasks versus the reasoning for the naming of category bitmasks, and not how to determine who has contacted whom.

Confused
  • 6,048
  • 6
  • 34
  • 75

2 Answers2

2

In almost all physics engines, collision layers are represented by bit masks. All objects in the same collision layers will collide with each other. In the bit mask, each layer is represented by a bit. If the bit at position 0 is on, the object will collide with other objects which have the bit at the same position in their bit mask on.

While checking for collisions, the physics engine's broad-phase routine only reports those pairs as potentially colliding which have at least one common bit set to 1 in their collision bit mask. This check is simply done by ANDing (&) the two bit masks. The potentially colliding pair is reported to the narrow-phase routine only if the above check returns a non-zero result.

For example, if you wanted the blue ball to collide with both the red and white balls but wanted the red and white balls to not collide with each other, you'd set the bit masks to somewhat the following:

Blue  -> 0b0011
Red   -> 0b0001
White -> 0b0010

In your example, since none of the bodies have a common bit set in their collision bit mask, none of them collide with each other. In the above example, since the red and white balls don't have a common bit in their bit mask, they don't collide.

You might want to set all the collision bit masks to -1 (which turns all bits on) and remove bits/categories from the mask by XORing. The above example would then be implemented by the following pseudocode:

blueBody.collisionMask = -1;
whiteBody.collisionMask = -1;
redBody.collisionMask = -1;

redBodyCategory   = 0b0001;
whiteBodyCategory = 0b0010;

whiteBody.collisionMask ^= redBodyCategory;
redBody.collisionMask ^= whiteBodyCategory;

I don't use SpriteKit, but from the little information I obtained from this SO answer, the contactTestBitmask sets the categories with which events will be raised on contact, while the collisionBitmask sets the categories with which the body will actually collide. So if you want contact information only from contacts which involve the Blue ball, you'd set the contactTestBitmask to the values as in my example above.

To check which balls are colliding with each other, you'd have to check the bit mask values and discern which one is which. In the above example, the Blue ball can be recognized by checking if body.contactTestBitmask == 0b0011, and so on for each other body.

As a side note, you might want to look into using a proper game engine like Unity that will make all this much easier.

Community
  • 1
  • 1
EvilTak
  • 7,091
  • 27
  • 36
  • "a proper game engine like Unity" made me laugh. There's nothing proper about Unity. But thank you for the rest. I'm still not sure I get it. But this is a very good answer. I'm going to need to think about this some more. – Confused Oct 08 '16 at 07:15
  • @Confused I personally find Unity one of the best and most modular engines out there, but if you don't like Unity, there still are many other options like Unreal. Also check out my latest edit. – EvilTak Oct 08 '16 at 07:17
  • I think the biggest three problems I'm having are 1. Bitwise operations, bitwise relationships and bitwise logic. – Confused Oct 08 '16 at 07:17
  • The size of both Unity and Unreal is the issue, for iOS development, and their shoddy performance. Unreal, I'll grant you, is a proper game engine. – Confused Oct 08 '16 at 07:18
  • The masking part seems to make pretty good sense. it's, as you say, kind of like layers. The really annoying issue I have is that I can't see how you determine something like my 3rd part of this question, which is which of the two balls that have contacted each other is the biggest? – Confused Oct 08 '16 at 07:19
  • Perhaps I've not made the question super clear, either. I want all collisions off, and to know about all contacts, and in those contacts, I always want to be informed which was the bigger ball involved in the contact between any two balls. HOW is that done. I don't need code, just an explanation of how the processes work, what's happening, and why... – Confused Oct 08 '16 at 07:21
  • This is why I've given the balls unique bitmasks. I thought this was part of the way to solving the problem of determining which was the bigger ball in any contact. – Confused Oct 08 '16 at 07:22
  • @Confused you should then set the `categoryBitmask` to be unique like you did but set the `contactTestBitmask` to values in my example. The behind the scenes explanation is in my answer. – EvilTak Oct 08 '16 at 07:34
  • In your example you only set collisionBitmasks for two out of the three objects. And the other example is about preventing collisions. – Confused Oct 08 '16 at 07:35
  • I'm not seeing the behind-the-scenes part of your answer that explains how to know which is the bigger ball in any contact. – Confused Oct 08 '16 at 07:36
  • If you can, could you spell it out, like I'm stupid, without code. Just something like: Making each contact bitmask unique ensures that any OR contacts indicate two bodies being these two of the three because... (I have no idea...) – Confused Oct 08 '16 at 07:39
  • 1
    @Confused setting unique collision masks will not help. Setting unique category bitmasks will help you do what you want. You need to check whether the category mask is equal to the unique mask value of each object or not. For example, `redCategory = 0b0010; if(contactBody.categoryMask == redCategory) { // contactBody is the red ball }` A category bitmask helps identifying which category the body belongs to. Each bit in the collision and contact test bit masks corresponds to a category. If a bit is on, collisions/contact events for that category are on. – EvilTak Oct 08 '16 at 16:53
  • argh, this is a big insight, for me! – Confused Oct 09 '16 at 13:23
  • I've added a little update of where my understanding is at, can you help with the last couple of points I make at the bottom of Update 2? – Confused Oct 09 '16 at 21:26
1

First, you need to define what your sprites are, this is what the categoryBitMask is for. Think of this as a binary name for your sprite, with each digit being a unique name. Now it is possible to give your sprite more than 1 name, but for simplicity purposes, let's keep it to one.

contactBitMask tells the sprites what names it should be looking for.

So during the physics phase, the engine will take a given sprite, and look for all other physics sprites with the search name provided in the contactBitMask.

After this, evaluations are performed against the original sprite and the sprites in the filtered list.

On a contact, didBegin(contact:) is called, and contact contains all the information you need, including the 2 contact bodies. You then check the categoryBitMask to get the name of the sprites in question, and you do your conditioning based on these names.

Knight0fDragon
  • 16,609
  • 2
  • 23
  • 44