SKPhysicsContactDelegate not works

I wanna add a score when the character contacts with the 'coins' and game over when it contacts with the 'enemies'. But it doesn't work. I compiled the ...Category and <SKPhysicsContactDelegate> code in GameScene.h and these:

- (instancetype)initWithSize:(CGSize)size {
    if (self = [super initWithSize:size]) {
        self.character = [SKSpriteNode spriteNodeWithImageNamed:@"character"];
        self.character.position = CGPointMake(100, 100);
        [self addChild:self.character];
        self.physicsWorld.gravity = CGVectorMake(0,0);
        self.physicsWorld.contactDelegate = self;
    }
    return self;
}

in .m above didMoveToView method. Can I use initWithSize in Xcode 8? And I do use these code in .m:

character.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:character.size]; //1
character.physicsBody.dynamic = YES; //2
character.physicsBody.categoryBitMask = characterCategory; //3
character.physicsBody.contactTestBitMask = coinCategory | enemiesCategory;//4
character.physicsBody.collisionBitMask = 0; // 5

I use them in "setPhysicsBody:(SKPhysicsBody *)physicsBody" method. And of couse I compiled the didBeginContact method. Did I miss anything? Please help me. Thank you very much.

Replies

Is your didBeginContact actually testing if two bodies are contacting. Paste in what you have there too.


Wish you were using Swift. I'd have some better examples for ya, but its been a while since I used Obj-C

Actually I've tested it. But when the moving character contacted with the 'coin, the 'coin' didn't disappear, it was pushed by the character and move too. Another question: how to paste the image in the Developer Forum's post. And does anyone can help me with Objective C? Thanks

A contact and collision are two different things. Collision means the two bumped into each other and can't occupy the same space (like in real life, you can't walk through a wall). In Sprite Kit you can decide whether or not two bodies collide with each other.


This is separate than whether or not they are listening for a contact each other. The contact can occur in both cases of collision (whether they can occupy the same space or bump off each other).


From your code above it looks like your character is listening for a contact with the coin. And the collisionBitMask is 0 so it shouldn't be colliding with anything. So maybe the coin isn't setup correclty.


But keep in mind, you didn't paste in the didBeginContact statement so I have no idea whether thats setup right.

  • This was super helpful, thanks!

Add a Comment

Thanks for help .So what are your suggestions to make the coin disappear if character contacted with it. I've change the collsionBitMask from 0 to 1. For more infomation, please see the code:

- (void)didBeginContact:(SKPhysicsContact *)contact {
    SKSpriteNode *character = [SKSpriteNode spriteNodeWithImageNamed:@"character"];
    SKSpriteNode *coin = [SKSpriteNode spriteNodeWithImageNamed:@"coin"];
    SKSpriteNode *enemy = [SKSpriteNode spriteNodeWithImageNamed:@"enemy"];
    
    SKPhysicsBody *firstBody, *secondBody;
    if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
    {
        firstBody = contact.bodyA;
        secondBody = contact.bodyB;
    }
    else
    {
        firstBody = contact.bodyB;
        secondBody = contact.bodyA;
    }
   

    if (((contact.bodyA.categoryBitMask) == !0) || ((contact.bodyB.categoryBitMask) == !0))
    {
        [self addCoincharacter didCollideWithBanana:coin];
    }
   
    if((contact.bodyA.categoryBitMask & mangoCategory ) == !0 || ( contact.bodyB.categoryBitMask & mangoCategory ) == !0 )
    {
        [self gameOver];
    }

Here's some changes...


- (void)didBeginContact:(SKPhysicsContact *)contact { 
    if (contact.bodyA.categoryBitMask ==  characterCategory.rawValue && contact.bodyB.categoryBitMask == coinCategory.rawValue )
    {
        //Body A was the character and Body B was the coin
    }
    if (contact.bodyA.categoryBitMask ==  coinCategory.rawValue && contact.bodyB.categoryBitMask == characterCategory.rawValue )
    {
        //Test the opposite, this time Body A was the coin and Body B was the character
    }


Again, my Obj-C is a little rusty, this is right in theory. You want to test the categoryBitMask against the characterCategory and coinCategory you established earlier. You need to check if body A was the character and Body B was the coin AND the vice versa of that. So you'll always have two if statements when testing different bodies colliding.


Within those if statements, you can do some casting to check if contact.bodyA.node is a particular class, then do something class-specific to the object. But if you just want to remove the body you can call removeFromParent on any node.

What can I write for the "raw value"?

And anything else I've missed? Please help. Thank you very much

.rawValue is a Swift thing. In Objective C, you'd use standard bit and bitmask operations.


BOOL character_coin = (contact.bodyA.categoryBitMask & characterCategory) && (contact.bodyB.categoryBitMask & coinCategory);
BOOL coin_character = (contact.bodyA.categoryBitMask & coinCategory) && (contact.bodyB.categoryBitMask & characterCategory);
if (character_coin || coin_character) { ... }

Thank you so much. I understand your explanation. I do it in this way in didBeginContact

if ((contact.bodyA.categoryBitMask == characterCategory) && (contact.bodyB.categoryBitMask == bananaCategory))

But SKPhysicsContactDelegate still not working. I found out the reason but it's just a maybe.

SKSpriteNode *character =[[SKSpriteNode alloc] initWithImageNamed:@"player.png"];

    character.name = @"character";
   
    character.physicsBody =
    [SKPhysicsBody bodyWithRectangleOfSize:character.frame.size];
    character.physicsBody.usesPreciseCollisionDetection = YES;
    character.physicsBody.categoryBitMask = characterCategory;
    character.physicsBody.collisionBitMask = characterCategory| coinCategory | enemyCategory;
    character.physicsBody.contactTestBitMask = characterCategory | coinCategory | enemyCategory;

Actually, I have no image named "player" but I do have images named "player 1", "player 2", etc so that I can make the animation of the player. So, do I have to write the code above multiple times? Or do you have other ways? Please help. Thank you.

I have some updates. When the character contacts with the banana, banana disappears, but the score is either 45, over 100 or over 200. I just want 1. Also I got lots of the crash logs of didBeginContact. Can anyone please help me? Is it the sign of spring? Please help. Thanks