How To Create A Game Like Tiny Wings with Cocos2D 2.X Part 2

In this second part of this Tiny Wings tutorial series, you’ll learn how to add the main character to the game, and use Box2D to simulate his movement. By Ali Hafizji.

Leave a rating/review
Save for later
Share
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

Fixing a Shaky Seal

You may notice when trying out the level that the seal switches rotation in a shaky manner as he slides along the ground.

One way to fix this is to take the weighted average of the past few linear velocities instead of always setting the position on the current velocity.

Let’s try this out. Add the following to Hero.mm:

// Add to top of file
#define NUM_PREV_VELS   5

// Add inside @interface
b2Vec2 _prevVels[NUM_PREV_VELS];
int _nextVel;

And modify the update method as follows:

- (void)update {
    
    self.position = ccp(_body->GetPosition().x*PTM_RATIO, _body->GetPosition().y*PTM_RATIO);
    b2Vec2 vel = _body->GetLinearVelocity();
    b2Vec2 weightedVel = vel;
    
    for(int i = 0; i < NUM_PREV_VELS; ++i) {
        weightedVel += _prevVels[i];
    }
    weightedVel = b2Vec2(weightedVel.x/NUM_PREV_VELS, weightedVel.y/NUM_PREV_VELS);    
    _prevVels[_nextVel++] = vel;
    if (_nextVel >= NUM_PREV_VELS) _nextVel = 0;
    
    float angle = ccpToAngle(ccp(weightedVel.x, weightedVel.y));     
    if (_awake) {   
        self.rotation = -1 * CC_RADIANS_TO_DEGREES(angle);
    }
}

This takes the average of the past 5 velocities instead of always taking just the linear velocity. Compile and run, and now you should see a much smoother seal!

Smoothly rotating seal

Zooming Out

One cool effect that Tiny Wings does is it zooms out the level the higher you go. This not only keeps the hero in view, but it adds to a cool feeling that you’re really moving!

To add this, simply add the following lines after the call to [_hero update] in HelloWorldLayer.mm‘s update method:

CGSize winSize = [CCDirector sharedDirector].winSize;
float scale = (winSize.height*3/4) / _hero.position.y;
if (scale > 1) scale = 1;
_terrain.scale = scale;

If the hero is at winSize.height*3/4, the scale will be 1. If he is < winSize.height*3/4, the scale will increase. If he is > winSize.height*3/4, the scale will decrease, effectively zooming out.

Compile and run, and see how high you can fly!

Zoom-out effect with seal flying high into the air

Gratuitous Animation and Music

You know I couldn’t leave you guys hanging without some gratuitous animation and music!

Will only take a second for a bit more awesomeness! Start by making the following changes to Hero.mm:

// Add inside @interface
CCAnimation *_normalAnim;
CCAnimate *_normalAnimate;

Then add the following method declarations in the Hero.h file:

// Add after @interface
- (void)nodive;
- (void)runForceAnimation;
- (void)runNormalAnimation;

This just declares the animation you’ll be creating, and the methods you’ll call whenever the seal is NOT diving.

Next make the following modifications to Hero.mm:

// Add new methods
- (void)runNormalAnimation {
    if (_normalAnimate || !_awake) return;
    _normalAnimate = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:_normalAnim]];
    [self runAction:_normalAnimate];
}

- (void)runForceAnimation {
    [_normalAnimate stop];
    _normalAnimate = nil;
    [self setDisplayFrame:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"seal_downhill.png"]];
}

- (void)nodive {
    [self runNormalAnimation];
}

// Add at bottom of initWithWorld:
_normalAnim = [[CCAnimation alloc] init];
[_normalAnim addSpriteFrame:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"seal1.png"]];
[_normalAnim addSpriteFrame:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"seal2.png"]];
[_normalAnim setDelayPerUnit:0.1];

This creates an animation for when the seal is moving normally, and a method to run that animation. The “animation” for diving is actually just a single frame, so we add a helper method to set that too.

Finally make a few changes to HelloWorldLayer.mm:

// At top of file
#import "SimpleAudioEngine.h"

// At end of onEnter
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"TinySeal.caf" loop:YES];

// At start of update, add an else case for the if (_tapDown):
else {
    [_hero nodive];
}

// Inside ccTouchesBegan
[_hero runForceAnimation];

// Inside ccTouchesEnded AND ccTouchesCancelled
[_hero runNormalAnimation];

Finally go to Terrain.mm and comment out the call to _world->DrawDebugData in the draw method.

Compile and run the code, and now your seal can ride the hills in style!

Finished game like Tiny Wings

Where To Go From Here?

Here is the sample code from the above tutorial.

At this point, you have a basic game working. Why not try to tweak the behavior of the seal so he moves in a more natural way up and down the hills? Or start adding in items to pick up, decorations on the hills, points to collect – your imagination is the only limit!

If you extend the game to add any cool new features or have any comments or questions, please join the forum discussion below!

Ali Hafizji

Contributors

Ali Hafizji

Author

Over 300 content creators. Join our team.