Search code examples
iphoneobjective-ccocos2d-iphonecollision-detectionbox2d

Box2d - Detecting single collisions only


I am writing a game that keeps a score of how many balls have been hit - the idea is to hit as many as possible. I am using Cocos2d and Box2d to do the physics and collision detection.

The scoring works but sometimes balls will end up moving along side each other, when this happens multiple collisions are recorded. Ideally I want only one collision to be recorded (i.e. score++) for each real collision.

What would be the best method to achieve this as I want the score to increase if two balls hit more than once but only if they actually collide as opposed to scraping alongside each other.

Im currently using the following code in my tick function

//detect collisions
std::vector<MyContact>::iterator pos;
for(pos = _contactListener->_contacts.begin(); 
    pos != _contactListener->_contacts.end(); ++pos) {
    MyContact contact = *pos;

    b2Body *bodyA = contact.fixtureA->GetBody();
    b2Body *bodyB = contact.fixtureB->GetBody();
    if (bodyA->GetUserData() != NULL && bodyB->GetUserData() != NULL) {
        NSLog(@"Collision!");

        score++;
        [scoreLabel setString:[NSString stringWithFormat:@"Score: %d", score]];
    }    
}

Solution

  • You are only checking to see if there was any collision at all. You need to check which objects collided and record that.

    For example:

    Generally I will step through my collisions as you are doing but I will record the sprite and or body in an array. As you are checking through collisions, do a check to ensure that your array hasn't already stored that sprite/body. If it has, you have already done that collision, and if it hasn't, store the collision. Then after all my collisions are checked, I remove any sprites and bodies and add my points.

    The contact listener will report a contact for both bodyA hitting bodyB, AND bodyB hitting bodyA. Those are two different collisions as far as the contact listener is concerned.