今天和大家分享的是使用cocos2dx引擎如何读取excle文件。在游戏开发中,游戏对象的属性,是写在一张表里面的,例如在红警中,每个兵种的攻击值,升级所需要的经验,造建筑所画的钱,这些都是写在数据表里面的。因为这些数据,数值策划经常要修改这些数值。如果直接硬编码,改动量是很大的,因此我们就把这些数据保存在一张excle表里面或者csv格式的文件中。
我的编译环境是:vs2012+coocs2dx3.6+cocos studio1.6+win7,如果不匹配,那我也没办法。
首先,将数据表转化为json文件。因为cocosdx中,内嵌了rapidjson,这个可以解析json文件。
打开coocs studio,选择:文件-》导入模板表-》选择对应的文件格式。
等到添加进去之后,选择导出json。
具体操作细节,参考这边博客:
http://blog.sina.com.cn/s/blog_ad1675150101fd6d.html
等到json文件制作完成,将它放到res文件下。新建一个数据类:
<span style="font-size:24px;color:#333333;">#ifndef __TOWER_DATE_H__
#define __TOWER_DATE_H__
#include"cocos2d.h"
#include<string>
USING_NS_CC;
using namespace std;
class TowerDate
{
public:
int id;//
const char* name;
int spreed;
int spreedpro;//速度权重
int attack;//攻击
int attackpro;//攻击权重
int ice;
int fire;//攻击火属性
int range;//攻击范围
int type;//攻击类型
public:
TowerDate(void);
~TowerDate(void);
};
#endif</span>
然后定义一个数据转换类:
<span style="font-size:24px;color:#333333;">#ifndef __TOWER_DATE_UNTIL_H__
#define __TOWER_DATE_UNTIL_H__
#include"cocos2d.h"
#include "json/rapidjson.h"
#include "json/document.h"
#include<map>
#include<string>
#include"TowerDate.h"
using namespace std;
USING_NS_CC;
class TowerDateUntil
{
public:
static TowerDateUntil* getInstance();
TowerDate getTowerDate();
private:
static TowerDateUntil* instance;
void initmapdate();
map<int,TowerDate> towermap;
public:
TowerDateUntil(void);
~TowerDateUntil(void);
};
#endif</span>
要注意的是:
map<int,TowerDate> towermap;这一句,一般我们都是这样处理的,将被存储为数据和该数据的id存放在一个映射表里面。这里的int,对应的就是防御塔的id,它和它的数据建立一种映射。
这里还使用了单例设计模式,如果不了解,请参见我之前写的设计模式中的单例模式。
Cpp文件
<span style="font-size:24px;color:#333333;">#include "TowerDateUntil.h"
//1
TowerDateUntil* TowerDateUntil::instance=new TowerDateUntil();
//1
TowerDateUntil* TowerDateUntil::getInstance()
{
return instance;
}
TowerDateUntil::TowerDateUntil(void)
{
initmapdate();
}
void TowerDateUntil::initmapdate()
{
//2
string filename=cocos2d::FileUtils::getInstance()->getStringFromFile("date1.json");
//3
rapidjson::Document m_doc;
//4
m_doc.Parse<0>(filename.c_str());
string str=filename;
//5
rapidjson::Value &pjson=m_doc["json"];
for(int i=0;i<pjson.Capacity();i++)
{
TowerDate d;
rapidjson::Value &temp=pjson[i];
d.id=temp["id"].GetInt();
//6
d.name=temp["name"].GetString();
d.spreed=temp["spreed"].GetInt();
d.spreedpro=temp["spreedpro"].GetInt();
//7
towermap.insert(make_pair(i,d));
}
}
TowerDateUntil::~TowerDateUntil(void)
{
}</span>
说明:
1. 这里使用了单例模式的饿汉单例模式,它是线程安全的。
2. 这是coco2dx处理文件的通用工具类。
/**
* Gets string from a file.
*/
virtual std::string getStringFromFile(const std::string& filename);
这是函数的说明
3. 这就是coco2dx内嵌的解析json的工具,使用这个要包含下列头函数:
#include "json/rapidjson.h"
#include "json/document.h"
具体介绍和使用参见这篇博客,值得说明的是,这个框架是腾讯写的,作者经常出现在知乎。
http://blog.csdn.net/elloop/article/details/49908689
4. 这一步要说明的是:Parse这个函数,是个函数模板,源码如下:
//! Parse JSON text from a read-only string.
/*! \tparam parseFlags Combination of ParseFlag (must not contain kParseInsituFlag).
\param str Read-only zero-terminated string to be parsed.
*/
template <unsigned parseFlags>
GenericDocument& Parse(const Ch* str) {
RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
GenericStringStream<Encoding> s(str);
return ParseStream<parseFlags>(s);
}
首先传入一个unsigned parseFlags,然后传入文件,这里是字符指针,如果你不是很了解函数模板,还是先去看看相关知识。
还有就是:typedef GenericDocument<UTF8<> > Document;这是一个自定义类型,其中GenericDocument这是一个模板类。
6这一步中要注意:这个函数
//!@name String
constCh*GetString()const{ RAPIDJSON_ASSERT(IsString()); return data_.s.str; }
其中
union Data {
String s;
Number n;
Object o;
Array a;
};// 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
struct String {
const Ch* str;
SizeType length;
unsigned hashcode;//!< reserved
};// 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
也就是说,在数据类设置name这个变量时,不能将它设置为string标准库中的变量,只能该设置为字符指针。
7.这里要简单的介绍一下pair容器。这个容器的详细介绍会在之后的文章里面和顺序容器,关联容器一起讲解。
Pair保存两个数据成员,他是一个用来生成特定类型的模板,当创建一个pair时,我们必须提供两个类型名,pair的数据成员将具有对应的类型,这两个类型不要求一样。
Pair的数据成员都是公共的,两个成员分别命名为first何second,可以直接用成员访问符号来访问他们。
其中,make_pair(v1,v2),返回一个用v1hev2初始化的pair,它的类型,从v1和v2反推出来。
还有就是,map要操作insert函数,插入类型必须是pair类型
源码下载: