Detecting collisions in sprite kit

that guy picture that guy · Dec 13, 2013 · Viewed 17.2k times · Source

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.

Answer

ZeMoon picture ZeMoon · Dec 16, 2013

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.