0
votes

I'm developing an iPhone game with cocos2d, box2d for iPhone. I have one problem here. enter image description here

As you can see from the screenshot above, these balls are b2Body. Every goes right, except one thing. When I tap on a ball, I want it to be removed from the screen, and it works well.

However, I need all of the connected balls with the same color to be removed too. For example, when I tap the red ball in the bottom, every red balls which are intersected with this tapped ball should be removed too.

This method manages the tap position

- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

    for( UITouch *touch in touches ) {
    CGPoint location = [touch locationInView: [touch view]];

    location = [[CCDirector sharedDirector] convertToGL: location];
    b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);

    // go through every single b2Body
    for(b2Body *b = world->GetBodyList(); b; b=b->GetNext()) {    
        if (b->GetUserData() != NULL) {

            b2Fixture *bf = b->GetFixtureList();

            // check which ball is tapped
            if (bf->TestPoint(locationWorld)) {
                [self destroyBall:b];
            }
        }        
    }
}

The "destroyBall" method is a recursive method, which is written as below

- (void) destroyBall:(b2Body *)body_ {
CCSprite *bodySprite = (CCSprite *) body_->GetUserData();
CGFloat h2 = bodySprite.contentSize.height / 2;
CGFloat w2 = bodySprite.contentSize.width / 2;

b2Vec2 p1 = b2Vec2((bodySprite.position.x - w2) / PTM_RATIO, (bodySprite.position.y - h2) / PTM_RATIO);
b2Vec2 p2 = b2Vec2((bodySprite.position.x - w2) / PTM_RATIO, (bodySprite.position.y + h2) / PTM_RATIO);
b2Vec2 p3 = b2Vec2((bodySprite.position.x + w2) / PTM_RATIO, (bodySprite.position.y + h2) / PTM_RATIO);
b2Vec2 p4 = b2Vec2((bodySprite.position.x + w2) / PTM_RATIO, (bodySprite.position.y - h2) / PTM_RATIO);

// go through all b2Body to check which one is intersect with body_
for (b2Body *b = world->GetBodyList(); b; b = b->GetNext()) {
    if ((b->GetUserData() != NULL) && (b != body_)) {
        CCSprite *newBall = (CCSprite *)b->GetUserData();

        b2Fixture *bf = b->GetFixtureList();
        if (bf->TestPoint(p1) || bf->TestPoint(p2) || bf->TestPoint(p3) || bf->TestPoint(p4)) {
            if (bodySprite.tag == newBall.tag) {
                [self destroyBall:b];
            }
        }
    }
}

CCSpriteBatchNode *batch = (CCSpriteBatchNode *) [self getChildByTag:kTagBatchNode];
[batch removeChild:bodySprite cleanup:YES];

world->DestroyBody(body_);
}

The idea is very simple, when the ball A is tapped, it looks for other balls around which are hitting ball A. If ball B is the one, the process will go again with ball B until there's no hitting ball.

However, the recursive function seems to run non-stop :(

I do appreciate if you have any idea or any algorithm to do this feature with box2d

Thank you very much for your support.

Thang

1
look up b2Body->GetContactList() here: learn-cocos2d.com/api-ref/latest/Box2D/html/…LearnCocos2D
yes, this GetContactList() would help. However, I want to take a "recursive check" to get the contacted balls of the contacted balls. However, it raise an "stack overflow" error :(Thang Tran

1 Answers

0
votes

I found the solution myself. I made a big and terrible mistake in recursive method, that I did't make a stop point, so the method just runs forever.

The ball just keeps checking around and around, I didn't mark the "found & going to delete balls".

I fixed it by creating an NSMutableArray and add the CCSprite into this NSMutableArray when a contacted ball is found. And the recursive method just call for the balls which are not found in that NSMutableArray