cocos2d-x SimpleGame(6)百尺竿头,更进一步

这个简单的游戏已经基本成型了,但我们可以把这个项目装饰得更完美。


在这一章,我们将添加新的场景。当一定数量的敌人被消灭,就在屏幕上显示”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()对应

言归正传,GameOverScene在某些场景中会被用到:干掉了一定数量的敌人或者敌人从屏幕右边跑到屏幕左边。

我们在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




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值