本人初学cocos2d-x ,记录学习过程中的学习笔记,写得不好请见谅
公司做的项目要用到地图编辑器,策划直接发了个mapwin给我,第一次碰这样的东西,实在是有点懵了,幸好在一同事的指点下,找到了点门路,mappy (不知道是mapwin还是mappy ,貌似在百度上,两种叫法都搜得到 = =!! 以下就用mappy 吧)。mappy 的编辑器,主要是让开发者可以更直观的去创建一张地图,并得到相对应的数据文档,mappy 中支持把创建的地图导出txt格式的文档,大概的的数据格式是这样的
const short xxx_map0[m][n] = {{x,x,x,x,},{x,x,x,x}};
const short xxx_map1[m][n] = {{x,x,x,x,},{x,x,x,x}};
xxx 只是个代替哈 = = !,其中const short 可以在导出txt文档的设置中取消掉,有人会说,自己输出的txt 后面还跟着一串貌似是颜色值之类的字符串,这个在输出的设置中都可以取消掉
接下来就是解析这个txt文件,放到二维数组里。
这里我创建了两个类来存储
- class DataMapLayer;
- class DataReadMap
- {
- public:
- DataReadMap();
- ~DataReadMap();
- static DataReadMap* Instance();
- void purgeInstance();
- void loaddata();
- void clear();
- public:
- vector<DataMapLayer*> m_MapList;
- private:
- int m_MapLayerNum;
- //void removeCharFromString(std::string mStr,char mCh);
- };
- class DataMapLayer
- {
- public:
- DataMapLayer();
- ~DataMapLayer();
- void loaddata(std::string mStr);
- void clear();
- std::string RemoveChFromStr(std::string mStr,char mCh);
- std::vector<std::string> SplitString(std::string mStr,char mCh);
- public:
- int m_Cols; //列
- int m_Rows; //行
- string m_Str;
- int **m_MapData;
- };
其中DataMapLayer 是来存储各个地图层的数据
DataReadMap 来存储总的地图 vector<DataMapLayer*> m_MapList,来存储各个层。
- void DataReadMap::loaddata()
- {
- this->clear();
- unsigned long fileSize ;
- //读取文档中的数据,将其存入fileChars ,fileSize 记录字符的个数
- char * fileChars = (char*)CCFileUtils::sharedFileUtils()->getFileData(CCFileUtils::sharedFileUtils()-> fullPathFromRelativePath("PROJA.TXT"), "rt", &fileSize);
- string mapString;
- mapString.assign(fileChars,fileChars+fileSize);
- int MapLayerNum = 0;
- //找出层数
- string tempString = mapString;
- int tempPos = 0;
- while ((tempPos = tempString.find('=')) != -1)
- {
- MapLayerNum++;
- tempStringtempString = tempString.substr(tempPos + 1);
- }
- //CCLOG("MapLayerNum :%d",MapLayerNum);
- m_MapLayerNum = MapLayerNum;
- string* mapLayer = new string[MapLayerNum];
- tempString = mapString;
- //分割成两个多个String
- for (int i = 0; i < MapLayerNum; i++)
- {
- mapLayer[i] = tempString.substr(tempString.find('c'));
- mapLayer[i] = mapLayer[i].substr(0,mapLayer[i].find(';'));
- tempStringtempString = tempString.substr(tempString.find(';') + 1);
- }
- //将各个层的数据放入m_MapList;
- for (int i = 0; i < m_MapLayerNum; i++)
- {
- DataMapLayer *datamaplayer = new DataMapLayer();
- datamaplayer->loaddata(mapLayer[i]);
- m_MapList.push_back(datamaplayer);
- }
- }
char * fileChars = (char*)CCFileUtils::sharedFileUtils()->getFileData(CCFileUtils::sharedFileUtils()->fullPathFromRelativePath("PROJA.TXT"), "rt", &fileSize);
先将文本里的数据读入fileChars 里,由于cocos2d-x里的函数返回类型是unsigned char* ,我就直接转成char* 不知道会不会有啥坏的影响。
由于每一个层是数据都是以 const short 开头,以 "};"作为结尾,所以判断“;” 的个数便可知道地图有几层,然后再将string以"c"与";"为起始点跟终止点,获得其中的字符串,便可获得一个完整的层的数据 const short xx_map0[m][n] = {......},有几层就创建几个DataMapLayer,将分割好的字符串传入其中解析,并将其存到m_MapList 的容器里,便于以后使用。
- void DataMapLayer::loaddata(std::string mStr)
- {
- m_Str = mStr;
- //解析行列数
- //取得 '=‘之前的字符串 (const short xxx [n][m])
- string HeadString = m_Str.substr(0,m_Str.find('='));
- //输出HeadString 格式应为 (const short xxx [n][m])
- HeadStringHeadString = HeadString.substr(HeadString.find('[') + 1,HeadString.size());
- string tempString = HeadString.substr(0,HeadString.find(']')); //取得第一个'['与']'之间 的数值即行数
- m_Rows = atoi(tempString.c_str());
- CCLOG("Rows:%d",m_Rows);
- HeadStringHeadString = HeadString.substr(HeadString.find('[') + 1,HeadString.size());
- tempString = HeadString.substr(0,HeadString.find(']')); //取得第二个'['与'['之间的数字,即列数
- m_Cols = atoi(tempString.c_str());
- CCLOG("Cols:%d",m_Cols);
- //动态创建二维数组
- m_MapData = new int *[m_Rows];
- for (int i = 0; i < m_Rows; i++)
- {
- m_MapData[i] = new int[m_Cols];
- }
- tempString = m_Str.substr(m_Str.find('=') + 1,m_Str.size()); //取得{} 之间的数据
- tempString = this->RemoveChFromStr(tempString, '{'); //去除'{'符号
- tempString = this->RemoveChFromStr(tempString, '}'); //去除'}'符号
- tempString = this->RemoveChFromStr(tempString, ' '); //去除空格
- std::vector<std::string> DataString = this->SplitString(tempString, ','); //将字符串以逗号为分隔,取出来
- int PosInStr = 0;
- //将数据存如二维数组
- for (int i = 0 ; i < m_Rows; i++)
- {
- for (int j = 0; j < m_Cols; j++)
- {
- if (PosInStr < DataString.size())
- {
- m_MapData[i][j] = atoi(DataString.at(PosInStr).c_str());
- PosInStr ++;
- }
- }
- }
- }
- void DataMapLayer::clear()
- {
- for (int i = 0; i < m_Rows; i++)
- {
- delete m_MapData[i];
- m_MapData[i] = NULL;
- }
- delete []m_MapData;
- m_MapData = NULL;
- }
- //从字符串中移除指定的字符
- std::string DataMapLayer::RemoveChFromStr(std::string mStr, char mCh)
- {
- string tempStr ;
- CCLog("Mstr len :%d",mStr.length());
- for (int i = 0; i < mStr.length(); i++)
- {
- if (mStr.at(i) != mCh)
- {
- tempStr.push_back(mStr.at(i));
- }
- }
- CCLOG("tempStr len:%d",tempStr.length());
- return tempStr;
- }
- //将字符串分割开
- std::vector<std::string> DataMapLayer::SplitString(std::string mStr, char mCh)
- {
- std::vector<std::string> tempStr;
- int pos ;
- while ((pos = mStr.find(mCh)) != -1)
- {
- tempStr.push_back(mStr.substr(0,pos));
- if (pos < (int)mStr.length() - 1)
- {
- mStrmStr = mStr.substr(pos + 1);
- }
- }
- if (mStr.length() > 0)
- {
- tempStr.push_back(mStr);
- }
- return tempStr;
- }
在DataMapLayer类里,传入一个完整的字符串形式的层数据 (const short xxmap..{.....};)取得二维数组的头字符串即 const short 到"="之间的这段,以"[""]"做判断,取出其行列数,动态创建一个二位数组,接下来就是解析字符串了。我的思路是,获得完整的一个{{...},{...}...};这样的字符串,于是我就取得 "=" 到字符串末尾的这段字符串或者说是"="到";",然后将其中的的"{","}"还有空格(mappy 导出的格式中两个数字之间是逗号加一个空格)去除掉,其他的都是(x,x,x,x,x,x,x)这样的格式,然后用SplitString函数将字符串以","为分隔,切成若干个字符串存到一个字符串容器里 std::vector<std::string> ,容器里的每一个字符串都是一个完整的数字,接下来就好办啦,用atoi 的方法,将其一个个放到二维数组中。这样就基本上大功告成了。不过得注意处理好析构的问题,
之前在网上找了一些解析的方法,好不容易找到几个,基本上都是解析单层的方法,好不容易参考同事的代码,自己瞎编了一个可以解析多层地图的方法, = =!! 解析是解析得了,就是不知道效率什么的怎么样,若有什么不足的地方,但请指出。╮(╯▽╰)╭ 学这样的东西,不久后就忘掉了,想想还是自己写点博客什么的来记录,一方面防止自己再次碰到相同的问题一时间手足无措,另一方面拿到网上来与大家做分享,有哪些地方写得不好,多多指教·
转载于:https://blog.51cto.com/jaonchung/1088053