Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are Sprite Kit's "Category Mask" and "Collision Mask"?

I am following the Sprite Kit guide, and in the scene editor it asks me to set the Category Mask to 32 and Collision Mask to 11. How are these numbers related?

like image 200
stefan s Avatar asked Nov 14 '16 16:11

stefan s


1 Answers

  • The Category bit mask tells Sprite-Kit what sort of object this is.
  • The Collision bit mask tells Sprite Kit what objects this object collides with (i.e. will hit and bounce off).
  • The ContactTest bit mask tells Sprite-Kit what contacts you want to be notified about i.e. when this object touches another object.

Collisions are handled automatically by the Sprite-Kit game engine; contacts are handled by your code - when a contact happens that you are interested in, your code (didBeginContact'for Swift 2,'didBegin(contact:) for Swift 3 and later) is called.

You need to think of these bitmasks in binary and for simplicity, we'll start with simple category bit masks, whereby each object in your scene belongs to only one category.

E.g. in your scene you have a player, a player-missile, an enemy and the screen-edge. We'll assume that the bit masks are 8-bit instead of 32-bit. Think of each number as a range of 8 binary digits (8 bits) each of which is a 0 or 1.

The objects in your scene have to have unique categories, so we'll assign them as follows:

player.categoryBitMask        = 00000001  (1 in decimal)
playerMissile.categoryBitMask = 00000010  (2 in decimal)
enemy.categoryBitMask         = 00000100  (4 in decimal)
screenEdge.categoryBitMask    = 00001000  (8 in decimal)

If you use numbers that are, in decimal, something other than a power of 2 (1, 2, 4, 8, 16, 32, 64, 128 etc) then more than 1 bit will be set in the category bit mask which complicates things (it means that this object belongs to multiple categories) and your code has to get more complicated.

Now think about what bounces off what (the collisions). Let's say everything bounces off everything else except the missile goes through the screen edge.

The collision bit masks for each object consists of the bits that represent the objects that this object collides with i.e.:

player.collsionBitMask         = 00001111 (15 in decimal) (the bits for all other objects are set)
playerMissile.collisionBitMask = 00000111 (7) (all object EXCEPT screenEdge)
enemy.collisonBitMask          = 00001111 (15) (everything)
screenEdge.collisonBitMask     = 00000000 (0) (collides with nothing)

Now we think about which object interactions we are interested in. We want to know when:

  • player and enemy touch
  • enemy and player touch or the enemy and the player's missile touch.

This is represented by:

player.contactTestBitMask = 00000100 (4) (the enemy's categoryBitMask)
enemy.contractTestBitMask = 00000011 (3) (the player's categoryBitMask combined with the missile's categoryBitMask))

Note that if you want to know when A and B touch, it's enough just to have A's contactTestBitMask (CTBM) to include B's categoryBitMask; you don't have to have B's CTBM set to A's category too. But if you want them to bounce off each other, then each object's collisionBitMask must include the other's categoryBitMask. If A's collisonbitMask includes B's category, but not vice versa, then when the 2 collide, A will bounce off but B will be unaffected by it.

For your specific example, (Category Mask to 32 and collision mask to 11), the categoryBitMask is 32 which is 00100000 (sticking with only 8 bits). The collisionBitMask is 11, which is 8 + 4 + 1 so in binary this is '00001101' which means it collides with objects with a categoryBitMask of 8, 4 or 1, so I assume that there are objects in your scene with these categoryBitMasks.

By default everything bounces off everything else i.e. the collisionBitMask is all '1's i.e. b'111111..' and nothing notifies of contacts with anything else i.e. contactTestBitMask is all '0's.

Also - all of this applies to physicsBodies, not nodes.

like image 84
Steve Ives Avatar answered Sep 30 '22 13:09

Steve Ives