在游戏开发中我们需要将玩家的游戏得分保存下来,同时做分数榜的时候我们也会用到玩家的得分情况,所以保存数据就很重要。我们使用的是CCUserDefault这个类来完成我们的功能,它使用起来比较简单,我原来的博客也有说明。本篇博客我们也来说一下如何监听键盘的返回键、菜单键和home键。首先明确一下什么时候需要保存游戏数据,当然是玩家本次游戏结束的时候,在我的例子中,玩家结束游戏是按了暂停按钮,弹出一个层,就是popscene这个类中,在quit和retry函数中我们会结束本次的游戏。当然你可以有自己的思路,但是玩家结束了本次游戏我们就应该保存一下这个分数。好了,那就来看看popScene这个类中我们做了哪些改动吧!

//在popScene中新增的头文件包含
//包含c++中的set容器和算法库
#include <set>
#include <algorithm>

我保存游戏数据是采用的set集合,这个集合是c++中的容器类,特点是里边的内容不可以重复,默认是按照元素的升序进行排序的,你也可以使用cocos2d-x中的集合,但是CCArray是没有排序功能的,需要用到c++中的sort函数,其他的俩个集合我不知道他们如何排序,所以就用了c++中的容器。

//新增的成员变量
public:
	//析构函数中delete掉set集合
	~PopScene(){delete score_set;};
	//对返回键的监听
	void keyBackClicked();
private:
	//创建set集合,用来保存玩家的分数
	std::set<int> * score_set;
	//数据保存类
	CCUserDefault * m_userDefault;
	//保存游戏数据
	void save();

看看在init函数中做了哪些改动,主要是初始化了set集合以及从XML文件中读取数据添加到set集合中。这里涉及到对XML文件是否存在的判断问题,不明白的可以看看我原来的博客。

bool PopScene::init()
{
	if(!CCLayerColor::initWithColor(ccc4(100,100,100,100)))
	{
		return false;
	}

	//创建三个菜单
	CCMenuItemImage * resume = CCMenuItemImage::create("resume.png","resume.png",
		this,menu_selector(PopScene::resume));
	CCMenuItemImage * retry = CCMenuItemImage::create("retry.png","retry.png",
		this,menu_selector(PopScene::retry));
	CCMenuItemImage * quit = CCMenuItemImage::create("quit.png","quit.png",
		this,menu_selector(PopScene::quit));

	CCMenu * menu = CCMenu::create(resume,retry,quit,NULL);
	menu->alignItemsVerticallyWithPadding(50);
	//添加到层中
	this->addChild(menu);

	//开启触摸,屏蔽下层对触摸的接受
	this->setTouchEnabled(true);

	//初始化set集合
	score_set = new std::set<int>();
	m_userDefault = CCUserDefault::sharedUserDefault();
	//首先判断XML文件是否存在,如果不存在的话就会执行if中的语句
	if(m_userDefault->getBoolForKey("isExit",false) == false)
	{
		//玩家初次玩游戏会执行这里
		m_userDefault->setBoolForKey("isExit",true);
		//设置分数记录的条数为0
		m_userDefault->setIntegerForKey("count",0);
	}
	else
	{
			//每玩一次游戏,分数的记录条数就会加一,这里加的一是上一次的记录
			m_userDefault->setIntegerForKey("count",(m_userDefault->getIntegerForKey("count"))+1);
			//为set集合赋值
			for(int i=0;i<m_userDefault->getIntegerForKey("count");i++)
			{
				CCString * index = CCString::createWithFormat("%d",i);
				score_set->insert(m_userDefault->getIntegerForKey(index->getCString()));
			}
	}

	//增加对返回键的监听
	this->setKeypadEnabled(true);

	return true;
}

接下来就是相当关键和重要的save函数了,每次保存游戏数据之前,都是先将本次游戏得分保存在了set中,之所以这么做是因为set有排序的功能,这样再保存到XML中的游戏数据就是有序的了,方便以后进行操作。这里用到一个getScore函数,是我新加的,在MyUILayer这个类中,返回玩家的得分情况。

void PopScene::save()
{
	//将玩家的分数保存到set集合中,以便排序,默认是按升序进行排序的
	int score = MyUILayer::sharedMyUILayer()->getScore();
	score_set->insert(score);

	//将玩家的得分保存在文件中
	std::set<int>::const_iterator iterator = score_set->begin();
	for(int i=0;i<score_set->size();i++)
	{
		CCString * index = CCString::createWithFormat("%d",i);
		m_userDefault->setIntegerForKey(index->getCString(),*iterator);
		iterator++;
	}
	//如果添加的分数是原来set集合中存在的set集合中是添加不进去的,因为set中保存的是没有重复值的元素
	//所以这里刷新一下count的值,以免产生bug
	m_userDefault->setIntegerForKey("count",score_set->size());
	m_userDefault->flush();
}

接下来就是什么时候调用save函数了,我在以下的俩个方法中调用了这个函数,保存了玩家的得分。这里的写法和做法只是提供了一种思路,其实玩家游戏数据的保存可以单独的放到一个类中去完成,什么时候保存游戏数据,就什么时候调用save,我这里为了省事,都写在了一个类中了,大家自由发挥吧!

void PopScene::retry(CCObject * obj)
{
	this->removeFromParentAndCleanup(true);

	//重置数据之前保存玩家刚才的得分
	this->save();

	//发送重置数据的消息
	CCNotificationCenter::sharedNotificationCenter()->postNotification(MESSAGE_TYPE_RESET_DATA,NULL);
}

void PopScene::quit(CCObject * obj)
{
	//返回到开始场景
	CCDirector::sharedDirector()->replaceScene(StartScene::scene());

	//保存玩家得分
	this->save();
}

说完了对游戏数据的保存,再说一下对按键的监听,第一,在init函数中需要开启按键,就是调用setKeypadEnabled方法,然后覆写虚函数keyBackClicked、keyMenuClicked完成对返回键和菜单键的监听,对home键的监听是在appDelegate函数中,那个引擎为我们写好了,这里我实现了对返回键的监听,大家根据自己的需要在不同的类中去监听吧。

//对返回键的监听
void PopScene::keyBackClicked()
{
	//将当前层清除从父节点中
	this->removeFromParentAndCleanup(true);
}

最后我们看一下这个保存了游戏数据的XML文件吧!

小塔1024——用户数据的保存和对返回键的监听