这个简单的游戏已经基本成型了,但我们可以把这个项目装饰得更完美。
在这一章,我们将添加新的场景。当一定数量的敌人被消灭,就在屏幕上显示”You Win“。如果有敌人跑到屏幕的左边,那么就在屏幕上显示”You Lose“。
现在在Classes路径中创建GameOverScene.h和GameOverScene.cpp两个文件。
GameOverScene.h中写进如下代码
#ifndef __GAME_OVER_SCENE_H_
#define __GAME_OVER_SCENE_H_
#include "cocos2d.h"
class GameOverLayer : public cocos2d::CCLayerColor
{
public:
GameOverLayer(void):_lable(NULL){};
~GameOverLayer(void);
bool init();
CREATE_FUNC(GameOverLayer);
void gameOverDone();
CC_SYNTHESIZE_READONLY(cocos2d::CCLabelTTF *, _lable, Lable);
};
class GameOverScene : public cocos2d::CCScene
{
public:
GameOverScene():_layer(NULL){};
~GameOverScene();
bool init();
CREATE_FUNC(GameOverScene);
CC_SYNTHESIZE_READONLY(GameOverLayer *, _layer, Layer);
};
#endif
温馨提示:
1.creat()方法对开发者来说非常方便,因为它集合了new()、init()、autorelease等方法。但C++中没有像obj-c中self那么强大的关键字,所以CCLayer::create()和CCScene::create()都需要我们在自己的文件中实现。由于create()方法都比较相似,所以我们实现了宏CREATE_FUNC()来方便大家使用,要使用它就必须在自己的文件中实现bool init()方法。
2._lable和_layer的setter和getter方法在obj-c中有@synthesize来实现,所以我们在cocos2dx\include\Cocos2dDefine.h文件中构造了一些宏来模仿这些功能。在上面的代码里,我们用CC_SYNTHESIZE_READONLY这个宏来实现_lable和_layer的只读方法,即getter()方法。在C++中,inline函数只能在头文件中定义,所以我们就在头文件中实现它。
GameOverScene.cpp文件中的代码
#include "GameOverScene.h"
#include "HelloWorldScene.h"
using namespace cocos2d;
bool GameOverScene::init()
{
if (CCScene::init())
{
// 初始化_layer
this->_layer = GameOverLayer::create();
// 为_layer增加索引计数
this->_layer->retain();
// 将_layer添加进场景
this->addChild(_layer);
return true;
}else
{
return false;
}
}
GameOverScene::~GameOverScene()
{
// 释放_layer
if (_layer)
{
_layer->release();
_layer = NULL;
}
}
bool GameOverLayer::init()
{
// 将背景设为白色
if (CCLayerColor::initWithColor(ccc4(255, 255, 255, 255)))
{
// 获得屏幕尺寸
CCSize size = CCDirector::sharedDirector()->getWinSize();
// 初始化_lable
this->_lable = CCLabelTTF::create("", "Artial", 32);
// 为_lable增加索引计数
this->_lable->retain();
// 将字体设为黑色
this->_lable->setColor( ccc3(0,0,0) );
// 把文字放在屏幕中间
this->_lable->setPosition(ccp(size.width/2, size.height/2));
// 延迟3秒后执行回调函数gameOverDone
this->runAction(CCSequence::create(
CCDelayTime::create(3),
CCCallFunc::create(this, callfunc_selector(GameOverLayer::gameOverDone)),
NULL));
// 把_lable添加进图层
this->addChild(_lable);
return true;
}else
{
return false;
}
}
void GameOverLayer::gameOverDone()
{
// 把当前场景切换为HelloWorldScene
CCDirector::sharedDirector()->replaceScene(HelloWorld::scene());
}
GameOverLayer::~GameOverLayer(void)
{
// 释放_lable
if (_lable)
{
this->_lable->release();
this->_lable = NULL;
}
}
在GameOverScene.cpp文件中有两个对象,一个是Scene(场景),一个是Layer(层)。一个场景可以包含多个层。在这个游戏中,我们只有一个层,在层的中心,会显示“You Win!”或“You Lose!”这样的文字。
温馨提示:
1. 再次注意GameOverLayer._label和GameOverScene._layer两个属性。这两个属性在objc的头文件里被声明为@property (nonatomic, retain),也就是被retain了一次,所以在dealloc里才要调用release方法。同样地,我们在~GameOverLayer()和~GameOverScene()析构函数里分别release()了这两个属性,但这个release需要和一个retain对应,所以在两个init方法里都分别添加了_label->retain()和_layer->retain();
2. 关于NSAutoReleasePool, cocos2d-x里也有个模仿实现,这个简单的垃圾回收机制对C++编程来说是个福音;它使用起来和iOS上的NSAutoReleasePool原则一样,参考苹果的文档 http://developer.apple.com/library/ios/#documentation/cocoa/reference/foundation/Classes/NSAutoreleasePool_Class/Reference/Reference.html
简而言之就是,在使用cocos2d-x中继承自NSObject类的对象指针时,以下两种情况是需要用户多调一个release
类对象是用户自己new出来的。比如CCSprite *sprite = new CCSprite();
类对象是通过某个静态函数建立并返回的,比如CCSprite *sprite = CCSprite::spriteWithFile(...),这种情况不需要用户release;但如果你接着调用了sprite->retain(), 那么就需要一个sprite->release()对应
我们在HelloWorldScene.h中添加变量 int _projectilesDestroyed来计算主角杀了多少敌人。
int _projectilesDestroyed;
在HelloWorldScene.cpp文件的构造函数中初始化
_projectilesDestroyed = 0;
在 HelloWorldScene.cpp中导入头文件GameOverScene.h
#include "GameOverScene.h"
当敌人和子弹发生碰撞后进行删除我们是在update方法中进行的,所以我们在update方法中删除敌人的代码后面加上如下代码
// 击中敌人数加1
_projectilesDestroyed++;
// 当击中5个敌人时,游戏结束,设置文字为You Win!并切换场景到结束画面
if (_projectilesDestroyed >= 5)
{
GameOverScene *gameOverScene = GameOverScene::create();
gameOverScene->getLayer()->getLable()->setString("You Win !");
CCDirector::sharedDirector()->replaceScene(gameOverScene);
}
敌人从屏幕右边跑到左边进行删除我们是在spriteMoveFinished方法中进行的,当tag等于1删除,我们在删除敌人的代码后面加上如下代码
// 当敌人从屏幕右方跑到左方时,游戏就结束,设置文字为You Lost!并切换场景到结束画面
GameOverScene *gameOverScene = GameOverScene::create();
gameOverScene->getLayer()->getLable()->setString("You Lost !");
CCDirector::sharedDirector()->replaceScene(gameOverScene);
现在万事俱备,只欠编译,所有的效果都齐全了,群魔乱舞,子弹横飞,很high的背景音乐还有游戏结束时的输赢提示。
整个游戏已经完工,欢呼吧。
附本章源码下载:http://download.csdn.net/detail/lpkkk/4997359
文章所写的东西只是我自己的理解,如果哪里出现错误,敬请斧正。
您可以留言、微博私聊我或Email我
我的微博:http://weibo.com/u/2007282737
我的Email:pengkailiao@gmail.com