Chapter 7 - Some Icing on the Cake

http://www.cocos2d-x.org/projects/cocos2d-x/wiki/Chapter_7_-_Some_Icing_on_the_Cake

 

Chapter 7 - Some Icing on the Cake

The simple game is completed basically, but we could add some adornments to make the game seem more professional.

In this chapter, we will add a new scene. When a certain quantity of monsters are killed, show “You Win” on the screen, and when there is a monster runs out of the left of the screen, show “You Lose”.

Now create two files GameOverScene.cpp and GameOverScene.h in the Classes directory.

For GameOverScene.h:
 1#ifndef _GAME_OVER_SCENE_H_
 2#define _GAME_OVER_SCENE_H_
 3
 4#include "cocos2d.h" 
 5
 6class GameOverLayer : public cocos2d::CCLayerColor
 7{
 8public:
 9    GameOverLayer():_label(NULL) {};
10    virtual ~GameOverLayer();
11    bool init();
12    LAYER_NODE_FUNC(GameOverLayer);
13
14    void gameOverDone();
15
16    CC_SYNTHESIZE_READONLY(cocos2d::CCLabelTTF*, _label, Label);
17};
18
19class GameOverScene : public cocos2d::CCScene
20{
21public:
22    GameOverScene():_layer(NULL) {};
23    ~GameOverScene();
24    bool init();
25    SCENE_NODE_FUNC(GameOverScene);
26
27    CC_SYNTHESIZE_READONLY(GameOverLayer*, _layer, Layer);
28};
29
30#endif // _GAME_OVER_SCENE_H_
 1#import "cocos2d.h" 
 2@interface GameOverLayer : CCLayerColor
 3{
 4    CCLabel *_label;
 5}
 6
 7@property (nonatomic, retain) CCLabel *label;
 8@end
 9
10@interface GameOverScene : CCScene 
11{
12    GameOverLayer *_layer;
13}
14@property (nonatomic, retain) GameOverLayer *layer;
15@end

Port Tips:

1.The class member functions could be realized in the .m file without declaration in the header file, but it is illegal in c++, so there is bool init(); in GameOverScene.h.

2. The function node() is convenient for developers because of integration of new, init, and autorelease, etc.. But there is no keyword like self(objc) in c++, so CCLayer::node() and CCScene::node() should be realized in their derived classes. The realization of node() is similar, we construct two macros to make the realization more essier: LAYER_NODE_FUNC and
SCENE_NODE_FUNC. To use the two macros, init() must be realized in the derived classes.

3. About constructors and init(). Cocos2d-x doesn’t port init() of objc to the constructor in c++ directly, because there is no return value in the c++ constructor, in this case, we have to handle exception with try-catch, but try-catch is not supported on android SDK. So, cocos2d-x initialize the classed in two stages, firstly calling the constructor and then doing initialization in init(). This method is also adopted in the interface design of iOS, for example, [[NSString alloc] init], and the utilization of c++ class in Samsung bada.

4. The setter and getter of _label and _layer are realized in @synthesize in objc, and we have constructed some macros in cocos2dx\include\Cocos2dDefine.h to simulate @property and @synthesize. In the codes above, CCX_SYNTHESIZE_READONLY defines the read-only member variable with only getter but not setter. In c++, the inline function can only be defined in the header file, so @synthesize is realized in the header file naturally.

For GameOverScene.cpp:

 1// cpp with cocos2d-x
 2#include "GameOverScene.h" 
 3#include "HelloWorldScene.h" 
 4
 5using namespace cocos2d;
 6
 7bool GameOverScene::init()
 8{
 9    if( CCScene::init() )
10    {
11        this->_layer = GameOverLayer::node();
12        this->_layer->retain();
13        this->addChild(_layer);
14
15        return true;
16    }
17    else
18    {
19        return false;
20    }
21}
22
23GameOverScene::~GameOverScene()
24{
25    if (_layer)
26    {
27        _layer->release();
28        _layer = NULL;
29    }
30}
31
32bool GameOverLayer::init()
33{
34    if ( CCLayerColor::initWithColor( ccc4(255,255,255,255) ) )
35    {
36        CCSize winSize = CCDirector::sharedDirector()->getWinSize();
37        this->_label = CCLabelTTF::labelWithString("","Artial", 32);
38        _label->retain();
39        _label->setColor( ccc3(0, 0, 0) );
40        _label->setPosition(ccp(winSize.width/2, winSize.height/2));
41        this->addChild(_label);
42
43        this->runAction( CCSequence::actions(
44        CCDelayTime::actionWithDuration(3),
45        CCCallFunc::actionWithTarget(this, 
46            callfunc_selector(GameOverLayer::gameOverDone)),
47            NULL));
48
49        return true;
50    }
51    else
52    {
53        return false;
54    }
55}
56
57void GameOverLayer::gameOverDone()
58{
59    CCDirector::sharedDirector()->replaceScene(HelloWorld::scene());
60}
61
62GameOverLayer::~GameOverLayer()
63{
64    if (_label)
65    {
66        _label->release();
67        _label = NULL;
68    }
69}
 1// objc with cocos2d-iphone
 2#import "GameOverScene.h" 
 3#import "HelloWorldScene.h" 
 4
 5@implementation GameOverScene
 6@synthesize layer = _layer;
 7
 8- (id)init
 9{
10    if ((self = [super init])) 
11    {
12        self.layer = [GameOverLayer node];
13        [self addChild:_layer];
14    }
15    return self;
16}
17
18- (void)dealloc 
19{
20    [_layer release];
21    _layer = nil;
22    [super dealloc];
23}
24
25@end
26@implementation GameOverLayer
27@synthesize label = _label;
28
29-(id) init
30{
31    if( (self=[super initWithColor:ccc4(255,255,255,255)] )) 
32    {
33        CGSize winSize = [[CCDirector sharedDirector] winSize];
34        self.label = [CCLabel 
35              labelWithString:@"" fontName:@"Arial" fontSize:32];
36
37        _label.color = ccc3(0,0,0);
38        _label.position = ccp(winSize.width/2, winSize.height/2);
39        [self addChild:_label];
40
41        [self runAction:[CCSequence actions:
42        [CCDelayTime actionWithDuration:3],
43        [CCCallFunc actionWithTarget:self 
44                            selector:@selector(gameOverDone)],
45                            nil]];            
46    }        
47    return self;
48}
49
50- (void)gameOverDone 
51{
52    [[CCDirector sharedDirector] 
53                         replaceScene:[HelloWorld scene]];      
54}
55
56- (void)dealloc 
57{
58    [_label release];
59    _label = nil;
60    [super dealloc];
61}
62
63@end

There are two objects in GameOverScene.cpp, one scene and one layer. A scene can involve several layers. In this game, there is only one layer, and in its center, a label with the words “You Win” or “You Lose” will be showed for three seconds.

Port Tips

1. Pay attention to GameOverLayer._label and GameOverScene._layer, they are declared in objc with @property (nonatomic, retain), it means that they are retained, so they should be released in dealloc. Similarly, there is retain() in init() of GameOverLayer and GameOverScene, and release() should be called in ~GameOverLayer() and ~GameOverScene() respectively.

2. NSAutoReleasePool is also ported in cocos2d-x. This Garbage Collector is good for c++ programming, and the utility is the same as in iOS, more information refers tohttp://developer.apple.com/library/ios/#documentation/cocoa/reference/foundation/Classes/NSAutoreleasePool_Class/Reference/Reference.html.
In cocos2d-x, we should call release() in two cases:
•    The object is newed by ourself, for example, CCSprite *sprite = new CCSprite();
•    The object is created by a static function, for example, CCSprite *sprite = CCSprite::spriteWithFile(...), in this case, we don’t need to release, but when sprite->retain() is called, then sprite->release() should be called too.

Then return to the issues, the GameOverScene should be called in some conditions: a certain number of monsters are killed or there is one monster escaped.

We add a variable in HelloWorldScene to count how many monsters are killed by the hero.

11 // cpp with cocos2d-x
22 protected:
33   int _projectilesDestroyed;    
11 // objc with cocos2d-iphone
22 
33 int _projectilesDestroyed;

And Initialize it in HelloWorld::HelloWorld(),

11 // cpp with cocos2d-x
2_projectilesDestroyed = 0;

Include GameOverScene.h in HelloWorldScene.cpp,

1// cpp with cocos2d-x
2#include "GameOverScene.h"    
1// objc with cocos2d-iphone
2#import "GameOverScene.h" 

After removeChild(target) in the targetsToDelete for loop of HelloWorld::update(), add the codes below to check the win condition.

1// cpp with cocos2d-x
2_projectilesDestroyed++;                       
3if (_projectilesDestroyed > 30)
4{
5  GameOverScene *gameOverScene = GameOverScene::node();
6  gameOverScene->getLayer()->getLabel()->setString("You Win!");
7  CCDirector::sharedDirector()->replaceScene(gameOverScene);
8}
 1   
 2// objc with cocos2d-iphone
 3_projectilesDestroyed++;
 4if (_projectilesDestroyed > 30)
 5{
 6  GameOverScene *gameOverScene = [GameOverScene node];
 7  [gameOverScene.layer.label setString:@"You Win!"];
 8  [[CCDirector sharedDirector] replaceScene:gameOverScene];
 9}

Add the codes below to check the failure condition in the “if (sprite->getTag() == 1)” conditional of spriteMoveFinished(),

1// cpp with cocos2d-x
2GameOverScene *gameOverScene = GameOverScene::node();
3gameOverScene->getLayer()->getLabel()->setString("You Lose :[");
4CCDirector::sharedDirector()->replaceScene(gameOverScene);    
1// objc with cocos2d-iphone
2GameOverScene *gameOverScene = [GameOverScene node];
3[gameOverScene.layer.label setString:@"You Lose :["];
4[[CCDirector sharedDirector] replaceScene:gameOverScene];

Now, everything is ready, compile and run, all kinds of effects will be showed, monsters everywhere, bullets everywhere, high background music and a prompt when you win or lose.

The whole game is completed now, cheers!

iPhone
android
win32
WoPhone

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值