首页 > 代码库 > cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第四步---编辑器(3)--坐标保存&加载文件操作

cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第四步---编辑器(3)--坐标保存&加载文件操作

/* 说明:

**1.本次游戏实例是《cocos2d-x游戏开发之旅》上的最后一个游戏,这里用3.0重写并做下笔记

**2.我也问过木头本人啦,他说:随便写,第一别完全照搬代码;第二可以说明是学习笔记---好人大笑

**3.这里用cocos2d-x 3.0版本重写,很多地方不同,但是从重写过程中也很好的学习了cocos2d-x

*/

***每一步对应的所有代码以及用到的资源都会打包在最后给出

***为避免代码过多,每一步的代码都做了标记--一看就晓得是第几步实现的避免出错改不回去(难不成还用Git?)

***可以根据设计思路(好吧,那名字太高大上。实际就是这一步要干啥)先自己实现---cocos2d-x本来就是如此,相同的功能有许多不同实现方法;先自己折腾是蛮不错的。

***为了方便移植到手机上,对于每一步都进行编译android测试;因为很多时候代码在win32下可以,编译就会出错,给出的代码会是测试过后的。

本次笔记内容:

1、稍微分析

2、看代码

3、下次内容预览

4、代码&资源下载

5、这里主要是文件操作;到这里编辑器部分也结束啦。后面就是游戏过程的设计啦

效果图---没啥效果,文件操作又看不出什么


那么到这里,先将代码分类下:


一:分析

1、我们可以先处理编辑不同关卡的实现,每次nextLvl的时候,将本层清空,重新加载地图

2、然后就是与文件挂钩,对于TowerPos和MonsterPos我们有对应容器保存;但是我们需要保存到文件中,为后面游戏加载做准备

二:代码

先处理简单的,编辑不同级别的关卡,添加 deleteAllPos函数,以及修改改变关卡的函数:

这里对于切换关卡实际上就是编辑层清空,重新加载其他关卡地图,进行编辑---(好吧,这里由于只有三个地图,就限制三个关卡,而且地图都是一样的.......)

 

[cpp] view plaincopy
  1. void TowerPosEditorLayer::deleteAllPos(){  
  2.     this->removeAllChildrenWithCleanup(true);  
  3.     m_monsterPosList.clear();  
  4.     m_towerPosList.clear();  
  5. }  
  6.   
  7. void TowerPosEditorLayer::nextLvl(){  
  8.     if(m_iCurLevel == 3){  
  9.         return ;  
  10.     }  
  11.     deleteAllPos();  
  12.     m_iCurLevel ++;  
  13.     loadConfigFile();  
  14. }  
  15.   
  16. void TowerPosEditorLayer::preLvl(){  
  17.     if(m_iCurLevel == 1){  
  18.         return;  
  19.     }  
  20.     deleteAllPos();  
  21.     m_iCurLevel --;  
  22.     loadConfigFile();  
  23. }  

到这也可以进行测试

------------------------------------------------------------------------------------

但是编辑过的地图怎么能不保存;而且,假若我编辑了第一关之后,保存,然后到第二关之后,我觉得第一关有一点点需要修改怎么办?

那么这里用一个坐标的文件操作  PosLoadUtil

这里又两个功能,加载已有的,和 把已有的输出到文件

需要小小的总结的是这是一个单例类,粗糙的了解一下单例类:

  比如你拍一部电影,今天在北京有一个场戏,明天去上海由一场戏;那么这里看做是两个场景,不同的场景,你导演总不会变:Director 应该就是一个单例类(我是这么理解的)

那么我们自己来弄一个单例类:独家供应饭店;首先是没有的,我们就create一个 ,它是static 的也就是存在整个电影的拍摄过程;随便你去哪里,打个电话::getInstence()--->送饭啦;就OK

上马:.h

 

[cpp] view plaincopy
  1. class PosLoadUtil : public Node{  
  2. public:  
  3.     static PosLoadUtil* getInstance();  
  4.     virtual bool init();  
  5.   
  6.     //**4**  
  7.     void putToFile(Vector<PosBase*> posList, const char* sFilePath);  
  8.   
  9.     //**4**选择传Vector<PosBase*>类型的引用  
  10.     void loadPosWithFile(Vector<PosBase*>& List,  
  11.         EnumPosType posType,  
  12.         const char* sFilePath,  
  13.         Node* container,  
  14.         int level,  
  15.         bool isDebug);  
  16.   
  17. private:  
  18.     static PosLoadUtil* _posLoadUtil;  
  19. };  

。cpp

 

[cpp] view plaincopy
  1. #include "PosLoadUtil.h"  
  2.   
  3. PosLoadUtil* PosLoadUtil::_posLoadUtil = NULL;  
  4.   
  5. PosLoadUtil* PosLoadUtil::getInstance(){  
  6.     if(_posLoadUtil == NULL){  
  7.         _posLoadUtil = new PosLoadUtil();  
  8.         if(_posLoadUtil && _posLoadUtil->init()){  
  9.             _posLoadUtil->autorelease();  
  10.         }else{  
  11.             CC_SAFE_DELETE(_posLoadUtil);  
  12.         }  
  13.     }  
  14.     return _posLoadUtil;  
  15. }  
  16.   
  17. bool PosLoadUtil::init(){  
  18.     return true;  
  19. }  
  20.   
  21. void PosLoadUtil::putToFile(Vector<PosBase*> posList, const char* sFilePath){  
  22.     FILE* file = fopen(sFilePath, "w");  
  23.   
  24.     // xml头部信息   
  25.     fprintf(file,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");  
  26.     fprintf(file,"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n");  
  27.   
  28.     // plist父节点字段开头   
  29.     fprintf(file,"<plist version=\"1.0\">\n");  
  30.   
  31.     // <array>   
  32.     fprintf(file,"<array>\n");  
  33.     // 各个属性   
  34.     PosBase* posBase = NULL;  
  35.     for(auto ref : posList) {  
  36.         posBase = dynamic_cast<PosBase*>(ref);  
  37.   
  38.         if(posBase != NULL) {  
  39.             // <dict>   
  40.             fprintf(file,"    <dict>\n");  
  41.   
  42.             // <key>x</key>   
  43.             fprintf(file,"        <key>x</key>\n");  
  44.   
  45.             // <integer>80</integer>   
  46.             fprintf(file,"        <integer>%.0f</integer>\n", posBase->getPos().x);  
  47.   
  48.             // <key>y</key>   
  49.             fprintf(file,"        <key>y</key>\n");  
  50.   
  51.             // <integer>266</integer>   
  52.             fprintf(file,"        <integer>%.0f</integer>\n", posBase->getPos().y);  
  53.   
  54.             // </dict>   
  55.             fprintf(file,"    </dict>\n");  
  56.         }  
  57.     }  
  58.     // </array>   
  59.     fprintf(file,"</array>\n");  
  60.   
  61.     // plist父节点字段结束   
  62.     fprintf(file,"</plist>\n");  
  63.   
  64.     fclose(file);   
  65. }  
  66.   
  67.  void PosLoadUtil::loadPosWithFile(Vector<PosBase*>& List,  
  68.      EnumPosType posType,  
  69.      const char* sFilePath,   
  70.      Node* container, int iLevel, bool isDebug ) {  
  71.   
  72.     // 读取plist文件   
  73.     auto value_Vector = FileUtils::getInstance()->getValueVectorFromFile(sFilePath);  
  74.   
  75.     for(auto ref : value_Vector) {  
  76.         //将value_Vector 里面读取的对象ref 转化为ValueMap 类型  
  77.         auto temp_map = ref.asValueMap();  
  78.   
  79.         //转化之后的ValueMap 对象 temp_map 取出x,y值  
  80.         auto x = temp_map.at("x").asFloat();  
  81.         auto y = temp_map.at("y").asFloat();  
  82.   
  83.         PosBase* posBase = PosBase::create(ccp(x,y), posType, isDebug);  
  84.   
  85.         List.pushBack(posBase);  
  86.   
  87.         container->addChild(posBase,iLevel);  
  88.     }  
  89. }  

然后,在PosEditorLayer中的文件输出函数中修改:

 

[cpp] view plaincopy
  1. void PosEditorLayer::outputPosToPlistFile(){  
  2.     CCLOG("outputPosToPlistFile");  
  3.     // 输出炮台坐标配置文件   
  4.     __String* sTowerPosPath = __String::createWithFormat("game/towerPos_level_%d.plist", _curLevel);  
  5.     PosLoadUtil::getInstance()->putToFile(m_towerPosList,sTowerPosPath->getCString());  
  6.   
  7.     // 输出怪物坐标配置文件   
  8.     __String* sMonsterPosPath = __String::createWithFormat("game/monsterPos_level_%d.plist", _curLevel);  
  9.     PosLoadUtil::getInstance()->putToFile(m_monsterPosList,sMonsterPosPath->getCString());  
  10. }  

在PosEditorLayer的preLoad函数中:

 

[cpp] view plaincopy
  1. void PosEditorLayer::preLoad(){  
  2.     /*******省略代码*********************** 
  3.     //加载TowerPos 
  4.     __String* sTowerPosPath =__String::createWithFormat("game/towerPos_level_%d.plist",_curLevel); 
  5.     PosLoadUtil::getInstance()->loadPosWithFile(m_towerPosList,  
  6.         enTowerPos, 
  7.         sTowerPosPath->getCString(), 
  8.         this,10,true); /**/  
  9.   
  10.     //加载MonsterPos  
  11.     __String* sMonsterPosPath = __String::createWithFormat("game/monsterPos_level_%d.plist", _curLevel);  
  12.     PosLoadUtil::getInstance()->loadPosWithFile(m_monsterPosList,   
  13.         enMonsterPos,  
  14.         sMonsterPosPath->getCString(),  
  15.         this,10,true);   
  16. }  

好吧,可以欢乐的测试啦,相应目录下也可以看到对应文件

当然,就算你最开始的目录下没有对应文件,你加载也不会出问题

小小的注意一下:这里怪物的路线点,得按顺序编辑之后再保存,不然后面怪物走的时候,是按照点的顺序走的。。。会乱走

三:下次内容预览

编辑了你想要的地图之后;开始了正式的游戏Scene;炮台的坐标点加载之后肯定在点的位置是要放置炮台的。。

cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第四步---编辑器(3)--坐标保存&加载文件操作