cocos2d box2d textured soft body physics

Download the demo source.

The soft body box2d code + texturing is all wrapped up in the SoftCircle class. I didn’t implement removal of a SoftCircle for this demo, but all you need to do is loop through the stl maps where the joints and bodies have been stored and destroy them.

If you want to change the behavior, modify the joint definition’s frequencyHz & dampingRatio.

Mega Bubble live & free on App Store :)

Mega Bubble is on the app store.. check it out, it’s free and fun!

box2d enable collisions between static/kinematic bodies

subclass b2body.cpp’s bool b2Body::ShouldCollide(const b2Body* other) const

or just comment out:

if (m_type != b2_dynamicBody && other->m_type != b2_dynamicBody)
{
    return false;
}

This is useful if you may need kinematic/static bodies to listen to collisions between each and also want to move them using cocos2d actions.

XCode behaviour

If you add abc.png to your app’s resources, build & run in the simulator/on device, then remove that file or rename it, it will still exist on the simulator/on device. This appears to be the case with shared libraries as well.

So make sure you remove your app/game from the test devices you were using during development, clean, then build & run in order to test a final time before final submission and after you’ve finished any modifications.

Using flood-fill to find unconnected nodes in bubble game

A previous blog post solved this algorithm with a recursive method.  Since then, it became necessary to improve the speed a little.

We will solve it the same way, using the flood/seed-fill algorithm (commonly used in graphics-editing programs Fill/Paint Bucket tool), but improve it by making it iterative and using c++ STL’s stack, vector, and map containers.


-(void) flagConnectedWithIndex:(int)index
{
    Enemytarget *targ = mapAllEnemies_[index];
    targ.connected = YES;

    stack stack;
    stack.push(index);

    while(!stack.empty()) {
        int currIdx = stack.top();
        stack.pop();

        vector neighbors = [self getNeighborsWithIndex:currIdx];
        for(unsigned int x = 0; x < neighbors.size(); x++) {
            int neighborIdx = neighbors[x];

            if(mapAllEnemies_[neighborIdx] != nil) {
                Enemytarget *t = mapAllEnemies_[neighborIdx];

                if(!t.connected) {
                    t.connected = YES;
                    stack.push(t.index);
                }
            }
        }
    }
}

In this method, mapAllEnemis_ is a 1d sparse index array containing all of the bubbles. It is using STL’s map. getNeighborsWithIndex is also using the STL vector class. If we use swap this class to return an NSArray of NSNumber objects, the flagConnectedWithIndex method finishes much more slowly.

In the screenshot, you see there are 9 nodes/bubbles max. per row. On even rows with the black labels, the row is shifted to the right 16 px. On odd rows, shifted to the left.

-(std::vector) getNeighborsWithIndex:(int)index
{
    vector surrIndices;         

    // right - black labels in screen cap
    if(index/Grid_Num_H %2 == 0) {
        if( (index+1) %Grid_Num_H != 1) {
            surrIndices.push_back( index - 1); // left
            surrIndices.push_back(index - Grid_Num_H -1); // bottom left
            surrIndices.push_back(index + Grid_Num_H -1); // top left
        }
        if( (index+1)  % Grid_Num_H != 0)
            surrIndices.push_back(index +1); // right

        surrIndices.push_back(index - Grid_Num_H); // bottom right
        surrIndices.push_back(index + Grid_Num_H); // top right
    }
    // left (white labels in screen capture)
    else {
        surrIndices.push_back(index - Grid_Num_H); // bottom left
        surrIndices.push_back(index + Grid_Num_H); // top left

        if(index % Grid_Num_H != 0 )
            surrIndices.push_back(index - 1); // left

        if(index % Grid_Num_H != 8 ) {
            surrIndices.push_back(index + 1); //right
            surrIndices.push_back(index - Grid_Num_H + 1); // bottom right
            surrIndices.push_back(index + Grid_Num_H + 1); // top right
        }
    }
    return surrIndices;
}

cocos2d move along a curve / bezier animation

I wanted to do a few things when displaying the points for an upcoming match 3 / bubble pop game I’m making:

1) After some bubbles are popped, add a points label at the position popped on the HUD layer. So we should have a delay before beginning this animation.
2) Animate this along a curve moving upward waving left and right
3) after traveling along the curve, scale the label to shrink it before it disappears
4) remove the label when finished

Some considerations:
– I will pass the method the position in the game layer to this method which is on the hud layer, and so we should convert the position using convertToWorldSpace as seen.

Implementation:

-(void) displayMsgWithPos:(CGPoint)sourcePos msg:(NSString*)str delay:(float)delay fontFile:(NSString*)fontFile
{
	CGSize s = [[CCDirector sharedDirector] winSize];
	CGPoint worldPos = [game_ convertToWorldSpace:sourcePos];
	
	CCLabelBMFont *label = [CCLabelBMFont labelWithString:str fntFile:fontFile];
	[label setPosition:worldPos];
	label.visible = NO;
	[self addChild: label];
	ccBezierConfig curve;
	curve.controlPoint_1 = ccp(worldPos.x -10, worldPos.y+10);
	curve.controlPoint_2 = ccp(worldPos.x +10, worldPos.y+20); 
	curve.endPosition = ccp(worldPos.x, worldPos.y+30);	
	
	id delayAction = [CCDelayTime actionWithDuration:delay];
	id addLabelAction = [CCShow action];
	id bezierMoveAction = [CCBezierTo actionWithDuration:1.0 bezier:curve];
	id scaleAction = [CCScaleTo actionWithDuration:0.5 scale:0.2];
	id actions = [CCSequence actions: delayAction, addLabelAction, bezierMoveAction, scaleAction, [CCCallFunc actionWithTarget:label selector:@selector(removeFromParentAndCleanup:)],nil];
	[label runAction:actions];
}

Follow me on google+ / twitter

Have some questions about game development with cocos2d?
Keep up to date on my newest games, and keep me up to date about yours.

google plus: gplus.to/dashiellgames

twitter: twitter.com/dashiellgames