3

I am detecting contacts from a ball and two edges of the screen (left and right one) For that purpose I created: – SKSpriteNode *ball – SKNode *leftEdge – SKNode *rightEdge

Here I am setting up the bit masks

static const uint32_t kCCBallCategory       = 0x1 << 0;
static const uint32_t kCCEdgeCategory       = 0x1 << 1;

Here I am adding the edges

leftEdge.physicsBody = [SKPhysicsBody bodyWithEdgeFromPoint:CGPointZero toPoint:CGPointMake(0.0, self.size.height)];
leftEdge.position = CGPointZero;
leftEdge.physicsBody.categoryBitMask = kCCEdgeCategory;
[self addChild:leftEdge];

Right edge is added exactly the same, except it has different name and position is set to

rightEdge.position = CGPointMake(self.size.width, 0.0);

Here I am configuring and adding the ball

ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:6.0];
ball.physicsBody.categoryBitMask = kCCBallCategory;
ball.physicsBody.collisionBitMask = kCCEdgeCategory;
ball.physicsBody.contactTestBitMask = kCCEdgeCategory;
[_mainLayer addChild:ball];

Later in didBeginContact I am checking if first body is the ball and the second body is the edge and adding some explosion to it

SKPhysicsBody *firstBody;
SKPhysicsBody *secondBody;
if (firstBody.categoryBitMask == kCCBallCategory && secondBody.categoryBitMask == kCCEdgeCategory) {
        // Collision between ball and the edge
        [self addExplosion:contact.contactPoint withName:@"BallEdgeBounce"];
    }

And the strange thing is – when the ball hits the left edge - code works fine and explosion effect added to the scene. But the right edge wont do the same. It came by surprise for me, because collisions works just fine. So why does the right edge behave like that? How do I fix this?

You could look at the project on the github, settings is done in GameScene.m file https://github.com/Fenkins/Space-Cannon

3 Answers3

2

I've looked into your Git project and this is happening because you have wrongly set category for rightEdge ( to be more precise, you haven't set it at all). You should do something like this:

SKNode *rightEdge = [[SKNode alloc]init];
rightEdge.physicsBody = [SKPhysicsBody bodyWithEdgeFromPoint:CGPointZero toPoint:CGPointMake(0.0, self.size.height)];
rightEdge.position = CGPointMake(self.size.width, 0.0);
// leftEdge.physicsBody.categoryBitMask = kCCEdgeCategory;//Error when copy/pasting ;-)
rightEdge.physicsBody.categoryBitMask = kCCEdgeCategory;
[self addChild:rightEdge];
Whirlwind
  • 14,286
  • 11
  • 68
  • 157
  • The OP has clearly written: "... Right edge is added exactly the same, except it has different name and position is set to ..." – ZeMoon Aug 13 '15 at 12:00
  • 1
    @ZeMoon I assumed that OP uses code which can be be found on Github link posted. If thats the case(there is a typo in his code), rightEdge.physicsBody.categoryBitMask is never set. What OP states in his question can be seen if you download and run project. If he follow my answer, he will get desired behaviour. At least his project works fine at my side and emitter is added when ball hits right wall. – Whirlwind Aug 13 '15 at 14:20
  • @Whirlwind is absolutely right, looks like I just mistyped edges names and setted leftEdge bitMask category two times... Thank you guys, I'll try to look better next time. – Anatoley Kovalev Aug 14 '15 at 08:37
0

You might have missed a simple practice carried out in the didBeginContact: method, of assigning the first and second bodies based on their categoryBitMask values.

-(void)didBeginContact:(SKPhysicsContact *)contact {
    SKPhysicsBody *firstBody;
    SKPhysicsBody *secondBody;

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

This needs to be done because there is no guarantee which body will be the first or the second.

Community
  • 1
  • 1
ZeMoon
  • 20,054
  • 5
  • 57
  • 98
  • yea, I was thinking about that, but that doesn't seems to be the issue. The thing is, I just mistyped the name for the edge while setting the right one bitMask... Thanks for your effort though. I'll try to look better for that kind of errors next time – Anatoley Kovalev Aug 14 '15 at 08:46
0

This is a different direction than where you seem to be going with your app, but it works.

SKSpriteNode *edgeLeft = [SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:CGSizeMake(1, self.frame.size.height)]; edgeLeft.physicsBody.collisionBitMask = kCCEdgeCategory; edgeLeft.position = CGPointMake(3, self.frame.size.height / 2); [self addChild:edgeLeft];

Then do the same for the top edge.

Hope this helped.

Michael Berk
  • 705
  • 7
  • 23