本人初学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文件,放到二维数组里。

这里我创建了两个类来存储

 

 
  
  1. class DataMapLayer; 
  2. class DataReadMap 
  3. public: 
  4.     DataReadMap(); 
  5.     ~DataReadMap(); 
  6.      
  7.     static DataReadMap* Instance(); 
  8.     void purgeInstance(); 
  9.     void loaddata(); 
  10.     void clear(); 
  11.      
  12. public: 
  13.     vector<DataMapLayer*> m_MapList; 
  14.      
  15. private: 
  16.     int     m_MapLayerNum; 
  17.      
  18.     //void removeCharFromString(std::string mStr,char mCh); 
  19. }; 
  20.  
  21. class DataMapLayer 
  22. public: 
  23.     DataMapLayer(); 
  24.     ~DataMapLayer(); 
  25.      
  26.     void loaddata(std::string mStr); 
  27.     void clear(); 
  28.     std::string RemoveChFromStr(std::string mStr,char mCh); 
  29.     std::vector<std::string> SplitString(std::string mStr,char mCh); 
  30.      
  31. public: 
  32.     int     m_Cols; //列 
  33.     int     m_Rows; //行 
  34.     string  m_Str; 
  35.     int     **m_MapData; 
  36. }; 

 

其中DataMapLayer 是来存储各个地图层的数据

DataReadMap 来存储总的地图 vector<DataMapLayer*> m_MapList,来存储各个层。

 

 

 
  
  1. void DataReadMap::loaddata() 
  2.  
  3.  
  4.     this->clear(); 
  5.  
  6.      
  7.  
  8.     unsigned long fileSize ; 
  9.  
  10.     //读取文档中的数据,将其存入fileChars ,fileSize 记录字符的个数 
  11.  
  12.     char * fileChars = (char*)CCFileUtils::sharedFileUtils()->getFileData(CCFileUtils::sharedFileUtils()-> fullPathFromRelativePath("PROJA.TXT"), "rt", &fileSize); 
  13.  
  14.     string mapString; 
  15.  
  16.     mapString.assign(fileChars,fileChars+fileSize); 
  17.  
  18.      
  19.  
  20.     int MapLayerNum = 0
  21.  
  22.      
  23.  
  24.     //找出层数 
  25.  
  26.     string tempString = mapString
  27.  
  28.     int tempPos = 0
  29.  
  30.     while ((tempPos = tempString.find('=')) != -1) 
  31.  
  32.     { 
  33.  
  34.         MapLayerNum++; 
  35.  
  36.         tempStringtempString = tempString.substr(tempPos + 1); 
  37.  
  38.     } 
  39.  
  40.     //CCLOG("MapLayerNum :%d",MapLayerNum); 
  41.  
  42.     m_MapLayerNum = MapLayerNum; 
  43.  
  44.     string* mapLayer = new string[MapLayerNum]; 
  45.  
  46.     tempString = mapString
  47.  
  48.      
  49.  
  50.     //分割成两个多个String 
  51.  
  52.      
  53.  
  54.     for (int i = 0; i < MapLayerNum; i++) 
  55.  
  56.     { 
  57.  
  58.         mapLayer[i] = tempString.substr(tempString.find('c')); 
  59.  
  60.         mapLayer[i] = mapLayer[i].substr(0,mapLayer[i].find(';')); 
  61.  
  62.         tempStringtempString = tempString.substr(tempString.find(';') + 1); 
  63.  
  64.     } 
  65.  
  66.      
  67.  
  68.     //将各个层的数据放入m_MapList; 
  69.  
  70.     for (int i = 0; i < m_MapLayerNum; i++) 
  71.  
  72.     { 
  73.  
  74.         DataMapLayer *datamaplayer = new DataMapLayer(); 
  75.  
  76.         datamaplayer->loaddata(mapLayer[i]); 
  77.  
  78.         m_MapList.push_back(datamaplayer); 
  79.  
  80.     } 
  81.  

 

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 的容器里,便于以后使用。

 

 

 
  
  1. void DataMapLayer::loaddata(std::string mStr) 
  2.  
  3.  
  4.     m_Str = mStr
  5.  
  6.      
  7.  
  8.     //解析行列数 
  9.  
  10.     //取得 '=‘之前的字符串 (const short xxx [n][m]) 
  11.  
  12.     string HeadString = m_Str.substr(0,m_Str.find('=')); 
  13.  
  14.     //输出HeadString 格式应为 (const short xxx [n][m]) 
  15.  
  16.      
  17.  
  18.     HeadStringHeadString = HeadString.substr(HeadString.find('[') + 1,HeadString.size()); 
  19.  
  20.     string tempString = HeadString.substr(0,HeadString.find(']'));  //取得第一个'['与']'之间 的数值即行数 
  21.  
  22.     m_Rows = atoi(tempString.c_str()); 
  23.  
  24.     CCLOG("Rows:%d",m_Rows); 
  25.  
  26.      
  27.  
  28.     HeadStringHeadString = HeadString.substr(HeadString.find('[') + 1,HeadString.size()); 
  29.  
  30.     tempString = HeadString.substr(0,HeadString.find(']'));     //取得第二个'['与'['之间的数字,即列数 
  31.  
  32.     m_Cols = atoi(tempString.c_str()); 
  33.  
  34.     CCLOG("Cols:%d",m_Cols); 
  35.  
  36.      
  37.  
  38.     //动态创建二维数组 
  39.  
  40.     m_MapData = new int *[m_Rows]; 
  41.  
  42.     for (int  i = 0; i < m_Rows; i++) 
  43.  
  44.     { 
  45.  
  46.         m_MapData[i] = new int[m_Cols]; 
  47.  
  48.     } 
  49.  
  50.      
  51.  
  52.     tempString = m_Str.substr(m_Str.find('=') + 1,m_Str.size());        //取得{} 之间的数据 
  53.  
  54.     tempString = this->RemoveChFromStr(tempString, '{');    //去除'{'符号 
  55.  
  56.     tempString = this->RemoveChFromStr(tempString, '}');    //去除'}'符号 
  57.  
  58.     tempString = this->RemoveChFromStr(tempString, ' ');    //去除空格 
  59.  
  60.     std::vector<std::string> DataString = this->SplitString(tempString, ',');       //将字符串以逗号为分隔,取出来 
  61.  
  62.     
  63.  
  64.     int PosInStr = 0
  65.  
  66.     //将数据存如二维数组 
  67.  
  68.     for (int i = 0 ; i  < m_Rows; i++) 
  69.  
  70.     { 
  71.  
  72.         for (int j = 0; j < m_Cols; j++) 
  73.  
  74.         { 
  75.  
  76.             if (PosInStr < DataString.size()) 
  77.  
  78.             { 
  79.  
  80.                 m_MapData[i][j] = atoi(DataString.at(PosInStr).c_str()); 
  81.  
  82.                 PosInStr ++; 
  83.  
  84.             } 
  85.  
  86.         } 
  87.  
  88.     } 
  89.  
  90.  
  91.  
  92.  
  93. void DataMapLayer::clear() 
  94.  
  95.  
  96.     for (int i = 0; i < m_Rows; i++) 
  97.  
  98.     { 
  99.  
  100.         delete m_MapData[i]; 
  101.  
  102.         m_MapData[i] = NULL; 
  103.  
  104.     } 
  105.  
  106.     delete []m_MapData; 
  107.  
  108.     m_MapData = NULL
  109.  
  110.  
  111.  
  112.  
  113. //从字符串中移除指定的字符 
  114.  
  115. std::string DataMapLayer::RemoveChFromStr(std::string mStr, char mCh) 
  116.  
  117.  
  118.     string tempStr ; 
  119.  
  120.     CCLog("Mstr len :%d",mStr.length()); 
  121.  
  122.     for (int i = 0; i < mStr.length(); i++) 
  123.  
  124.     { 
  125.  
  126.         if (mStr.at(i) != mCh) 
  127.  
  128.         { 
  129.  
  130.             tempStr.push_back(mStr.at(i)); 
  131.  
  132.         } 
  133.  
  134.     } 
  135.  
  136.     CCLOG("tempStr len:%d",tempStr.length()); 
  137.  
  138.      
  139.  
  140.     return tempStr; 
  141.  
  142.  
  143.  
  144.  
  145. //将字符串分割开 
  146.  
  147. std::vector<std::string> DataMapLayer::SplitString(std::string mStr, char mCh) 
  148.  
  149.  
  150.     std::vector<std::string> tempStr; 
  151.  
  152.     int pos ; 
  153.  
  154.     while ((pos = mStr.find(mCh)) != -1) 
  155.  
  156.     { 
  157.  
  158.         tempStr.push_back(mStr.substr(0,pos)); 
  159.  
  160.         if (pos < (int)mStr.length() - 1) 
  161.  
  162.         { 
  163.  
  164.             mStrmStr = mStr.substr(pos + 1); 
  165.  
  166.         } 
  167.  
  168.     } 
  169.  
  170.     if (mStr.length() > 0) 
  171.  
  172.     { 
  173.  
  174.         tempStr.push_back(mStr); 
  175.  
  176.     } 
  177.  
  178.      
  179.  
  180.     return tempStr; 
  181.  

 

在DataMapLayer类里,传入一个完整的字符串形式的层数据 (const short xxmap..{.....};)取得二维数组的头字符串即 const short 到"="之间的这段,以"[""]"做判断,取出其行列数,动态创建一个二位数组,接下来就是解析字符串了。我的思路是,获得完整的一个{{...},{...}...};这样的字符串,于是我就取得 "=" 到字符串末尾的这段字符串或者说是"="到";",然后将其中的的"{","}"还有空格(mappy 导出的格式中两个数字之间是逗号加一个空格)去除掉,其他的都是(x,x,x,x,x,x,x)这样的格式,然后用SplitString函数将字符串以","为分隔,切成若干个字符串存到一个字符串容器里 std::vector<std::string> ,容器里的每一个字符串都是一个完整的数字,接下来就好办啦,用atoi 的方法,将其一个个放到二维数组中。这样就基本上大功告成了。不过得注意处理好析构的问题,

    之前在网上找了一些解析的方法,好不容易找到几个,基本上都是解析单层的方法,好不容易参考同事的代码,自己瞎编了一个可以解析多层地图的方法, =   =!! 解析是解析得了,就是不知道效率什么的怎么样,若有什么不足的地方,但请指出。╮(╯▽╰)╭ 学这样的东西,不久后就忘掉了,想想还是自己写点博客什么的来记录,一方面防止自己再次碰到相同的问题一时间手足无措,另一方面拿到网上来与大家做分享,有哪些地方写得不好,多多指教·