数据:
对象使用大括号{ }表示,由键值对组成;键必须是字符串“ ”,值可以是任何类型。
数组使用[ ]表示。
Json关卡数据
[
{
"id":1001,
"name":"第一关",
"waves":
[
{
"enemyId":3001,
"count":3,
"interval":1,
"nextInterval":5
},
{
"enemyId":3001,
"count":4,
"interval":0.5,
"nextInterval":5
},
{
"enemyId":3002,
"count":5,
"interval":1,
"nextInterval":5
}
],
"bgImage":
[
"Image/Map1.png",
"Image/Map2.png"
]
},
{
"id":1002,
"name":"第二关",
"waves":
[
{
"enemyId":3002,
"count":4,
"interval":1,
"nextInterval":5
},
{
"enemyId":3001,
"count":5,
"interval":0.5,
"nextInterval":5
},
{
"enemyId":3002,
"count":6,
"interval":1,
"nextInterval":5
}
],
"bgImage":
[
"Image/Map2.png",
"Image/Map3.png"
]
}
]
DataBase.h
添加json的包含目录:点击工程->属性->C/C++ ->附加包含目录->编辑,添加新的包含目录 $(EngineRoot)external\json 往上移。 要么改成#include “json/rapidjson.h”。
#ifndef __DataBase_H__
#define __DataBase_H__
#include <vector>
#include <string>
#include "cocos2d.h"
//记得添加json的包含目录
#include "rapidjson.h"
#include "document.h"
using namespace std;
USING_NS_CC;
class CDataBase{
public:
virtual ~CDataBase(){}; //让子类重写虚函数释放new出来的对象
int nID;
};
//抽象类:抽象类不能被实例化
class CDataBaseMgr{
public:
virtual ~CDataBaseMgr();
void loadFile(const string& strPath);
//ifstream是windows特有的 改为使用json的
virtual void parse(rapidjson::Document& doc) = 0;
template <class T>
T getDataByID(int nID)
{
for (CDataBase* pData : m_VecData)
{
if (pData->nID == nID)
{
return static_cast<T>(pData);
}
}
return nullptr;
}
int getSize();
vector<CDataBase*>& getAllData();
protected:
vector<CDataBase*> m_VecData; //类型统一,通过容器存放,便于统一管理
};
#endif
DataBase.cpp
#include "cocos2d.h"
#include "DataBase.h"
USING_NS_CC;
CDataBaseMgr::~CDataBaseMgr()
{
for (CDataBase* pData : m_VecData)
{
CC_SAFE_DELETE(pData); //释放pLevelDt,因为pLevelDt继承于CDataBase
}
m_VecData.clear();
}
int CDataBaseMgr::getSize()
{
return m_VecData.size();
}
vector<CDataBase*>& CDataBaseMgr::getAllData()
{
return m_VecData;
}
//加载ison数据
void CDataBaseMgr::loadFile(const string& strPath)
{
string strFullPath = FileUtils::getInstance()->fullPathForFilename(strPath); //获取全路径
string strData = FileUtils::getInstance()->getStringFromFile(strFullPath); //获取该路径对应的json内容
rapidjson::Document doc; //将strData解析到doc中
doc.Parse(strData.c_str()); //由于Parse只接受char*类型,将string类型转化成char*类型
this->parse(doc); //调用parse从doc里吧东西解析出来
doc.Clear();
}
ConfigMgr.h
#ifndef __ConfigMgr_H__
#define __ConfigMgr_H__
#include <string>
#include <map>
#include "DataBase.h"
using namespace std;
class CConfigMgr
{
public:
CConfigMgr();
~CConfigMgr();
static CConfigMgr* getInstance();
void addData(const string& strKey, CDataBaseMgr* pData);
CDataBaseMgr* getData(const string& strKey);
private:
static CConfigMgr* m_pInstance;
map<string, CDataBaseMgr*> m_mapData;
};
#endif
ConfigMgr.cpp
#include "ConfigMgr.h"
#include "cocos2d.h"
CConfigMgr* CConfigMgr::m_pInstance = nullptr;
CConfigMgr::CConfigMgr()
{
}
CConfigMgr::~CConfigMgr()
{
for (map<string, CDataBaseMgr*>::iterator iter = m_mapData.begin(); iter != m_mapData.end(); ++iter)
{
CC_SAFE_DELETE(iter->second);
}
m_mapData.clear();
}
CConfigMgr* CConfigMgr::getInstance()
{
if (!m_pInstance)
{
m_pInstance = new CConfigMgr();
}
return m_pInstance;
}
void CConfigMgr::addData(const string& strKey, CDataBaseMgr* pData)
{
if (strKey.empty() || !pData)
{
return;
}
m_mapData.insert(pair<string, CDataBaseMgr*>(strKey, pData));
}
CDataBaseMgr* CConfigMgr::getData(const string& strKey)
{
map<string, CDataBaseMgr*>::iterator iter = m_mapData.find(strKey);
if (iter != m_mapData.end())
{
return iter->second;
}
return nullptr;
}
DataClass.h(各种具体的数据和数据管理者)
//怪物波
struct SWave
{
int nEnemyId;
int nCount;
float fInterval;
float fNextInterval;
};
//关卡数据
class CLevelDt : public CDataBase
{
public:
virtual ~CLevelDt();
string strName;
vector<SWave*> vecWaves; //怪物波(多个),用容器存储
vector<string> vecBgImage; //多张图片
};
//关卡数据管理者
class CLevelDtMgr:public CDataBaseMgr
{
public:
//重写parse:传入json格式的数据
virtual void parse(rapidjson::Document& doc);
};
//数据加载:游戏最开始时调用
class CLoader
{
public:
static void loadConfig();
};
DataClass.cpp(各种具体的数据解析过程)
CLevelDt::~CLevelDt()
{
for (SWave* pWave : vecWaves)
{
CC_SAFE_DELETE(pWave); //释放pWave
}
}
//一个节点一个节点地解析
void CLevelDtMgr::parse(rapidjson::Document& doc)
{
for (int i = 0; i < doc.Size(); i++) //文件数组[],存放多个关卡对象
{
rapidjson::Value& vLevel = doc[i]; //关卡对象{}
//new一个关卡数据pLevelDt(用于存放解析的关卡数据)
CLevelDt* pLevelDt = new CLevelDt();
pLevelDt->nID = vLevel["id"].GetInt(); //关卡对象的属性:关卡id
pLevelDt->strName = vLevel["name"].GetString(); //关卡名称
rapidjson::Value& vWaves = vLevel["waves"]; //怪物波数组[]
for (int j = 0; j < vWaves.Size(); j++) //遍历
{
rapidjson::Value& vWave = vWaves[j]; //怪物波{}
//new一个波数据结构体(用于存放解析的波数据)
SWave* pWave = new SWave();
pWave->nEnemyId = vWave["enemyId"].GetInt(); //怪物id
pWave->nCount = vWave["count"].GetInt(); //怪物数量
pWave->fInterval = vWave["interval"].GetFloat(); //怪物时间间隔
pWave->fNextInterval = vWave["nextInterval"].GetFloat(); //怪物波出现间隔
pLevelDt->vecWaves.push_back(pWave); //压入容器vecWaves
}
rapidjson::Value& vBgImage = vLevel["bgImage"]; //背景图数组
for (int k = 0; k < vBgImage.Size();k++) //背景图[]
{
string strImage = vBgImage[k].GetString(); //背景图
pLevelDt->vecBgImage.push_back(strImage); //压入容器vecBgImage
}
m_VecData.push_back(pLevelDt); //统一压到CDatabaseMgr下的m_VecData中
}
}
//整体的数据加载:加载各种DtMgr
void CLoader::loadConfig()
{
//先new出关卡数据管理者
CLevelDtMgr* pLevelDtMgr = new CLevelDtMgr();
//加载json数据
pLevelDtMgr->loadFile("Configs/LevelDt.json");
//在全局数据管理者中添加数据
CConfigMgr::getInstance()->addData("LevelDtMgr",pLevelDtMgr);
}
数据的使用
//关卡Id
CC_SYNTHESIZE(int, m_nLevelId, LevelId);
int nLevelId = CDynamicData::getInstance()->getLevelId();
//通过Id 获取关卡数据
CLevelDt* pLevelDt = CConfigMgr::getInstance()->getData("LevelDtMgr")->getDataByID<CLevelDt*>(nLevelId);
//通过关卡拿到怪物波(定义一个索引)
m_pCurWave = pLevelDt->vecWaves[m_nWaveIndex];