Detecting collisions in sprite kit

I'm trying to make a simple game with sprite kit. The basic idea is that there is one player who can jump to avoid blocks. But i have a problem I don't know how to make it that when the player hits the block the player disappears and the blood animation starts. First of all i don't understand what this code does that I found on apples website.

static const uint32_t blockCategory = 0x1 <<0;
static const uint32_t  playerCategory = 0x1 <<1;

Than i am calling the didBeginContact function and put a NSLOG("did call function") in it. But i never receive the output in my debugger.

Here is my _player and _block code: -(SKSpriteNode *)character {

_player = [SKSpriteNode spriteNodeWithImageNamed:@"soldier_run1"];
_player.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:_player.size.width /2 -5];
_player.physicsBody.dynamic = YES;
_player.physicsBody.usesPreciseCollisionDetection = YES;
_player.physicsBody.friction = 0;
_player.physicsBody.categoryBitMask = playerCategory;
_player.physicsBody.collisionBitMask = blokCategory;
_player.name = @"player";
SKAction *animAction = [SKAction animateWithTextures:playerTextures timePerFrame:0.1      resize:YES restore:YES];

My _player code:

[_player runAction:[SKAction repeatActionForever:animAction]];

return _player;
}
-(SKSpriteNode *)block {
_blok = [[SKSpriteNode alloc] initWithColor:[SKColor blackColor] size:CGSizeMake(15, 40)];

//physics
_blok.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_blok.size];
_blok.physicsBody.dynamic = NO;
_blok.name = @"block";
_blok.physicsBody.categoryBitMask = blokCategory;
_blok.physicsBody.collisionBitMask = playerCategory;
SKAction *moveBlock = [SKAction sequence:@[
                                          [SKAction moveToX:-20 duration:2] ]];
[_blok runAction:moveBlock ];
return _blok;
}

Also i don't really understand what the categoryBitMask and collisionBitMask do. After i have that working i would like to make the character disappear from the screen and the blood animation to start, but I have no idea how to let that happen. I think you have to do something like: if(_player && _block didcollide) { } But I don't know how to do it exactly.


Solution 1:

The categoryBitMask sets the category that the sprite belongs to, whereas the collisionBitMask sets the category with which the sprite can collide with and not pass-through them.

For collision detection, you need to set the contactTestBitMask. Here, you set the categories of sprites with which you want the contact delegates to be called upon contact.

What you have already done is correct. Here are a few additions you need to do:

_player.physicsBody.contactTestBitMask = blockCategory;
_blok.physicsBody.contactTestBitMask = playerCategory;

Afterwards, implement the contact delegate as follows:

-(void)didBeginContact:(SKPhysicsContact *)contact`
{
NSLog(@"contact detected");

SKPhysicsBody *firstBody;
SKPhysicsBody *secondBody;

if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
{
    firstBody = contact.bodyA;
    secondBody = contact.bodyB;
}
else
{
    firstBody = contact.bodyB;
    secondBody = contact.bodyA;
}

//Your first body is the block, secondbody is the player.
//Implement relevant code here.

}

For a good explanation on implementing collision detection, look at this tutorial.

Solution 2:

Handling collisions is a bit messy. :) There are a number of approaches, but one place you should start with is this fairly simple example from Apple. The readme provides a good intro, and then you can start poking around with the code.

Another approach (which Apple mentions in their guide) is to use Double Dispatching (see wikipedia for a long desc). I wouldn't start by trying to grok that approach right off however. It is a somewhat advanced approach given it depends on dynamic selectors and similar techniques to enable the magic to take place. However, even with that caveat, you can find a simple example someone put together on how to do it, along with a lot of supporting description here.