16

I'm looking at doing the best way to collect items with my hero in my spriteKit game for iOs, and after to try a few ways to do it, my conclusion is the best way would be to have an item with a physic body which can detect collisions but don't collide with my hero. Is it possible to do it? to deactivate collisions of a physic body without deactivating its capabilities to detect collisions?? Sounds a bit contradictory I know... Because, the other way would be to create only a SKSpriteNode without physic body, then there wouldn't being collisions, but the way to "detect" collisions would be hand made and much more harder, because i would need to set a coordinate system detection in my hero, that when he will be in those specifics coordinates (over the item) then i'll make the item disappears. Any idea of how to do any of the two ways easier?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Alfro
  • 1,524
  • 2
  • 21
  • 37
  • thats what are category bit masks for – santhu Jan 21 '14 at 20:05
  • if you hadn't read about them, goto page **96 of sprite kit PG**.Read "Collision and Contact Example: Rockets in Space" – santhu Jan 21 '14 at 20:06
  • it's incredibly stupid but Apple did NOT seem to put in something to simply disable physics on physicsBody. This means that, the basic fundamental technique of all game development, using a "model" which you clone - can't be done in iOS. Nice. – Fattie Oct 26 '17 at 21:54

4 Answers4

22

Check out collisionBitMask, categoryBitMask, and contactTestBitMask in the SKPhysicsBody class.

Essentially, physics bodies with the same collisionBitMask value will "pass-through" each other.

  • Correction: If the category and collision bits match, they will interact. If they do not match, those two will not interact. And if the collision bits, and category bits, are both zero, of course that item will interact with nothing whatsoever.

Then, you set the categoryBitMask and contactTestBitMask values to create an SKPhysicsContact Object on contact. Finally, your Class should adopt the SKPhysicsContactDelegate protocol. Use the - didBeginContact: method to detect and handle the SKPhysicsContact object.

static const uint8_t heroCategory = 1;
static const uint8_t foodCategory = 2;
--
food.physicsBody.categoryBitMask = foodCategory;
food.physicsBody.contactTestBitMask = heroCategory;
food.physicsBody.collisionBitMask = 0;
--
hero.physicsBody.categoryBitMask = heroCategory;
hero.physicsBody.contactTestBitMask = foodCategory;
hero.physicsBody.collisionBitMask = 0;
--
-(void)didBeginContact:(SKPhysicsContact *)contact {
    SKPhysicsBody *firstBody = contact.bodyA;
    SKPhysicsBody *secondBody = contact.bodyB;
}
Fattie
  • 27,874
  • 70
  • 431
  • 719
Corey
  • 5,818
  • 2
  • 24
  • 37
  • This answer needs better clarification, the reason why the two objects in this example will passthrough each other is because `collisionBitMask = 0` Which means "Do not collide with anything". If for some reason you want 2 of the same types of objects to collide with everything bit each other, then make sure that the collisionBitMask does not contain the flag used for the categoryBitMask – Knight0fDragon May 26 '17 at 13:18
8

Short answer:

yourHero.physicsBody.collisionBitMask = 0;

The default value of collisionBitMask is 0xFFFFFFFF (all bits set), that's why the node collides with others

Andrey Gordeev
  • 30,606
  • 13
  • 135
  • 162
4

you can do this by setting the categoryBitMask and contactBitMasks of the player and the item objects, but making sure that you do not set the collisionBitMask for either to interact with each other (see below)

static const int playerCategory = 1;
static const int worldCategory = 2;
static const int objectCategory = 4;    

....

SKSpriteNode *player, *item;

....

player.physicsBody.categoryBitMask = playerCategory;
player.physicsBody.collisionBitMask = worldCategory;
player.physicsBody.contactTestBitMask = worldCategory;

....

item.physicsBody.categoryBitMask = objectCategory;
item.physicsBody.contactTestBitMask = playerCategory | worldCategory;
item.physicsBody.collisionBitMask = worldCategory;

this way the physics body will pick up collisions between the player and world objects, the item and world objects, but not between the player and items. It will trigger a call to didBeginContact, where you can delete your item node, add health, etc.

Hope this helps!

ubersnack
  • 512
  • 6
  • 19
3

contactTestBitMask is used to trigger didBeginContact. collisionBitMask is used to activate physics on nodes.

// add a physics body
ship.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ship.size.width/2];

// set the category for ship
ship.physicsBody.categoryBitMask = shipCategory;

// detect collisions with asteroids and edges
ship.physicsBody.contactTestBitMask = asteroidCategory | edgeCategory;

// physically collide with asteroids
ship.physicsBody.collisionBitMask = asteroidCategory;
425nesp
  • 6,936
  • 9
  • 50
  • 61