分数排行榜的做法和我在小塔1024中的实现原理是一样的,这里用的是3.0的引擎,所以函数的参数有些许的不同,这里说明俩处需要注意的问题,一个是扩展库的问题,在3.0中扩展的项目是没有引入到工程中的,所以需要自己手动将扩展项目引入进来,这样才能使用TableView,方法请参考3.0回调函数的新用法。另一个问题是实现TableViewDelegate和TableViewDataSource的虚函数时候index参数的类型原来是unsigned int,3.0变成了ssite_t,这里需要注意一下,因为本人就是没有注意这个参数的类型导致出现了莫名其妙的错误,好了,代码如下。

#ifndef _SCORE_SCENE_H_
#define _SCORE_SCENE_H_
#include "cocos2d.h"
//使用tableview必须包含扩展库
#include "cocos-ext.h"

USING_NS_CC;
USING_NS_CC_EXT;

//分数榜场景,使用tableview必须继承以下的类
class ScoreScene : public Layer,public TableViewDataSource,public TableViewDelegate
{
public:
	ScoreScene(void);
	~ScoreScene(void);
public:
	static Scene * createScene();
	bool init();
	CREATE_FUNC(ScoreScene);
public:
	//实现上述接口需要实现的虚函数如下,这里有非常重要的一点就是函数的参数index原来2.x的版本类型为
	//unsigned int而现在改为了ssize_t类型,必须写这个类型,用原来的类型会出现错误,本人就是因为这个错误
	//耽误了很多的时间
	void tableCellTouched(TableView *table,TableViewCell * cell){}; //这里是设置当我们点击每个cell的时候触发的函数,这里我把它置为空的实现,因为我们只是需要读取分数的记录
	TableViewCell * tableCellAtIndex(TableView * table,ssize_t index);
	Size tableCellSizeForIndex(TableView * table,ssize_t index);
	//3.0的返回值有所不同
	ssize_t numberOfCellsInTableView(TableView * table);
	//继承ScrollViewDelegate接口需要覆写的方法,这里把方法的实现留空
	void scrollViewDidScroll(ScrollView * ){};
	void scrollViewDidZoom(ScrollView *){};
	//对android返回键的响应
	void onKeyReleased(EventKeyboard::KeyCode keyCode,Event * pEvent);
private:
	//设备尺寸
	Size size;
};

#endif
#include "ScoreScene.h"

ScoreScene::ScoreScene(void)
{
}

ScoreScene::~ScoreScene(void)
{
	//在析构函数中移除监听器,这里传递的参数this就是添加监听器到事件分发器中的this
	_eventDispatcher->removeEventListenersForTarget(this);
}

Scene * ScoreScene::createScene()
{
	auto scene = Scene::create();
	auto layer = ScoreScene::create();
	scene->addChild(layer);
	return scene;
}

bool ScoreScene::init()
{
	if(!Layer::init())
		return false;

	size = Director::getInstance()->getWinSize();

	//添加背景图片
	auto background = Sprite::createWithSpriteFrameName("background.png");
	background->setPosition(Point(size.width/2,size.height/2));
	this->addChild(background);

	//创建tableView并设置一些参数
	auto tableView = TableView::create(this,Size(size.width,size.height*0.6));
	//设置滑动方向
	tableView->setDirection(ScrollView::Direction::VERTICAL);
	//设置TableViewDelegate
	tableView->setDelegate(this);
	//index的大小是从上到下依次增大
	tableView->setVerticalFillOrder(TableView::VerticalFillOrder::TOP_DOWN);
	//用当前的配置刷新cell
	tableView->reloadData();
	this->addChild(tableView);

	//排行榜
	//排名
	auto rankNum = Label::createWithTTF("rank","font/arial.ttf",40);
	rankNum->setColor(Color3B(100,100,100));
	rankNum->setPosition(Point(size.width*0.4,size.height*0.7));
	this->addChild(rankNum);
	//得分
	auto rankScore = Label::createWithTTF("score","font/arial.ttf",40);
	rankScore->setPosition(Point(size.width*0.8,size.height*0.7));
	rankScore->setColor(Color3B(100,100,100));
	this->addChild(rankScore);

	//对用户返回键的响应
	auto listener = EventListenerKeyboard::create();
	listener->onKeyReleased = CC_CALLBACK_2(ScoreScene::onKeyReleased,this);
	_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);

	return true;
}

//对返回键的响应
void ScoreScene::onKeyReleased(EventKeyboard::KeyCode keyCode,Event * pEvent)
{
	if(keyCode == EventKeyboard::KeyCode::KEY_BACKSPACE)
		//将开始场景弹出
		Director::getInstance()->popScene();
}

//这个函数比较关键,是用来设置每个cell的内容的
TableViewCell * ScoreScene::tableCellAtIndex(TableView * table,ssize_t index)
{
	//设置每条记录前边的文本内容
	auto index_text = __String::createWithFormat("%ld",index+1);

	//dequeuecell这个函数是获得一个可用的cell,因为如果我们没增加一条分数记录就创建一个cell,可想而知如果
	//分数记录很多的话,cell不是超级的多了吗,这个时候内存占用就会很大,而这个函数的功能是把那些没有渲染的
	//cell拿过来,这样的话就减小了内存的消耗
	TableViewCell * cell = table->dequeueCell();
	if(cell == NULL)
	{
		//创建一个cell
		cell = new TableViewCell();
		cell->autorelease();

		//创建显示排名的文本信息
		auto text = Label::createWithTTF(index_text->getCString(),"font/arial.ttf",24);
		text->setTag(1024);
		text->setColor(Color3B(100,100,100));
		//文本信息在cell的中间
		text->setPosition(Point(size.width*0.4,size.height*0.025));
		cell->addChild(text);

		//显示用户得分的文本信息
		auto index_score = __String::createWithFormat("%d",index);
		//根据index值获得得分的文本,因为这个时候的score是int型,所以还需要转化一下类型,这里有点麻烦
		int i_score = UserDefault::getInstance()->getIntegerForKey(index_score->getCString());
		auto * str = __String::createWithFormat("%d",i_score);
		auto score = Label::createWithTTF(
			str->getCString(),"font/arial.ttf",24);
		score->setTag(2048);
		//设置坐标
		score->setPosition(Point(size.width*0.8,size.height*0.025));
		score->setColor(Color3B(100,100,100));
		cell->addChild(score);

	}
	//这里获得的cell是原来的cell,所以原来cell的文本信息等还是原来的,所以要做一些改变
	else
	{
		//通过tag值获得文本,并且改变,虽然LabelTTF调用setString函数不好,但是这里为了省事就这么用吧
		auto text = (Label *)cell->getChildByTag(1024);
		text->setString(index_text->getCString());

		//改变分数
		auto * score = (Label *)cell->getChildByTag(2048);
		auto * index_score = __String::createWithFormat("%d",index);
		//根据index值获得得分的文本,因为这个时候的score是int型,所以还需要转化一下类型,这里有点麻烦
		int i_score = UserDefault::getInstance()->getIntegerForKey(index_score->getCString());
		auto * str = __String::createWithFormat("%d",i_score);
		score->setString(str->getCString());

		if(cell->getChildByTag(100) != NULL)
		{
			Sprite * sprite = (Sprite *)cell->getChildByTag(100);
			sprite->removeFromParentAndCleanup(true);
		}
	}

	if(index == 0 || index==1 || index==2)
	{
		Sprite * sprite;
		switch(index)
		{
			//代表的是冠军
		case 0:
			sprite = Sprite::create("gold.png");
			break;
		case 1:
			sprite = Sprite::create("silvere.png");
			break;
		case 2:
			sprite = Sprite::create("tong.png");
			break;
		}
		sprite->setPosition(Point(size.width*0.15,size.height*0.025));
		sprite->setTag(100);
		cell->addChild(sprite);
	}

	return cell;
}

//这个函数是用来设置每个cell的大小的
Size ScoreScene::tableCellSizeForIndex(TableView * table,ssize_t index)
{
	return Size(size.width,size.height*0.05);
}

//这个函数是用来设置cell的个数的
ssize_t ScoreScene::numberOfCellsInTableView(TableView * table)
{
	//个数是从XML文件中读取到的,有多少条记录,就设置多少个cell,如果刚开始没有count这个字段,就返回0
	int count = UserDefault::getInstance()->getIntegerForKey("count",0);

	return count;
}

然后在开始游戏的场景中添加几个菜单用来选择进入分数榜的场景,代码如下。

//添加一个游戏开始按钮
	auto playText = Label::createWithTTF(((__String *)(dictionary->objectForKey("play")))->getCString(),
		"font/DFPShaoNvW5-GB.ttf",40);
	playText->setColor(Color3B(100,100,100));
	auto playMenu = MenuItemLabel::create(playText,CC_CALLBACK_1(StartGame::play,this));

	//添加分数榜按钮
	auto scoreText = Label::createWithTTF(((__String *)(dictionary->objectForKey("scoreMenu")))->getCString(),
		"font/DFPShaoNvW5-GB.ttf",40);
	scoreText->setColor(Color3B(100,100,100));
	auto scoreMenu = MenuItemLabel::create(scoreText,CC_CALLBACK_1(StartGame::scoreScene,this));

	//添加关于作者菜单
	auto authorText = Label::createWithTTF(((__String *)(dictionary->objectForKey("aboutMe")))->getCString(),
		"font/DFPShaoNvW5-GB.ttf",40);
	authorText->setColor(Color3B(100,100,100));
	auto authorMenu = MenuItemLabel::create(authorText,CC_CALLBACK_1(StartGame::aboutMe,this));

	auto menu = Menu::create(playMenu,scoreMenu,authorMenu,NULL);
	menu->alignItemsVerticallyWithPadding(30);
	menu->setPosition(size.width/2,size.height*0.3);
	this->addChild(menu);
//分数榜响应函数
void StartGame::scoreScene(Ref * ref)
{
	Director::getInstance()->pushScene(ScoreScene::createScene());
}

用3.0实现飞机大战——分数排行榜的实现

在移植的过程中遇到了一个小问题,提示fatal error: cocos-ext.h: No such file or d irectory,这是因为3.0扩展库是没有作为工程的一部分的,在win32下我们引入了工程extensions,才编译通过的,移植android的过程中,我们需要对mk文件做下修改。如图所示,然后移植,就成功了。

用3.0实现飞机大战——分数排行榜的实现