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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
How To Create A Game Like Tiny Wings with Cocos2D 2.X Part 2
25 mins
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!
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!
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!
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!