Cocos2d-x 深入解析系列 : 以XML文件方式保存用户数据

[Cocos2d-x相关教程来源于红孩儿的游戏编程之路CSDN博客地址 http://blog.csdn.net/honghaier

红孩儿Cocos2d-X学习园地

           Cocos2d-x 深入解析系列:以XML文件方式保存用户数据

另:本章所用Cocos2d-x版本为: 

2.1.1 (2013-01-28)


              大家好,今天我们来学习一下如何使用XML文件方式来保存游戏中的用户数据。在使用Cocos2d-x开发游戏的过程中,我们经常会使用XML来存储用户存档数据,而这些XML我们该如何生成呢?Cocos2d-x提供了一个类CCUserDefault以方便我们随时将需要的数据生成XML文件。

 

打开CCUserDefault.h:

[cpp]  view plain copy
  1. #ifndef __SUPPORT_CCUSERDEFAULT_H__  
  2. #define __SUPPORT_CCUSERDEFAULT_H__  
  3. //加入平台所用的头文件  
  4. #include "platform/CCPlatformMacros.h"  
  5. #include   
  6. //使用Cocos2d命名空间  
  7. NS_CC_BEGIN  
  8.   
  9. //定义类CCUserDefault  
  10. class CC_DLL CCUserDefault  
  11. {  
  12. public:  
  13.     //析构  
  14.     ~CCUserDefault();  
  15.   
  16.     //从指定的键中取得布尔值  
  17.     bool    getBoolForKey(const char* pKey);  
  18.     //从指定的键中取得布尔值,如果没有则返回默认参数  
  19.     bool    getBoolForKey(const char* pKey, bool defaultValue);  
  20.     //从指定的键中取得整数值  
  21.     int     getIntegerForKey(const char* pKey);  
  22.     //从指定的键中取得整数值,如果没有则返回默认参数  
  23.     int     getIntegerForKey(const char* pKey, int defaultValue);  
  24.      //从指定的键中取得浮点值  
  25.     float    getFloatForKey(const char* pKey);  
  26.     //从指定的键中取得浮点值,如果没有则返回默认参数  
  27.     float    getFloatForKey(const char* pKey, float defaultValue);  
  28.      //从指定的键中取得双精度值  
  29.     double  getDoubleForKey(const char* pKey);  
  30.     //从指定的键中取得双精度值,如果没有则返回默认参数  
  31.     double  getDoubleForKey(const char* pKey, double defaultValue);  
  32.      //从指定的键中取得字符串值  
  33.     std::string getStringForKey(const char* pKey);  
  34.     //从指定的键中取得字符串值,如果没有则返回默认参数  
  35.     std::string getStringForKey(const char* pKey, const std::string & defaultValue);  
  36.   
  37.     //设置指定键的布尔值  
  38.     void    setBoolForKey(const char* pKey, bool value);  
  39.     //设置指定键的整数值  
  40.     void    setIntegerForKey(const char* pKey, int value);  
  41.     //设置指定键的浮点值  
  42.     void    setFloatForKey(const char* pKey, float value);  
  43.     //设置指定键的双精度值  
  44.     void    setDoubleForKey(const char* pKey, double value);  
  45.     //设置指定键的字符串值  
  46.     void    setStringForKey(const char* pKey, const std::string & value);  
  47.     //立即将XML数据写入文件  
  48.     void    flush();  
  49.     //取得单例的指针  
  50.     static CCUserDefault* sharedUserDefault();  
  51.     //释放单例  
  52.     static void purgeSharedUserDefault();  
  53.     //取得保存后的XML文件路径  
  54.     const static std::string& getXMLFilePath();  
  55.   
  56. private:  
  57.     //因为是单例,构造函数私有化  
  58.     CCUserDefault();  
  59.     //创建XML文件  
  60.     static bool createXMLFile();  
  61.     //XML文件是否存在  
  62.     static bool isXMLFileExist();  
  63.     //初始化XML文件  
  64.     static void initXMLFilePath();  
  65.     //单例的指针  
  66.     static CCUserDefault* m_spUserDefault;  
  67.     //XML文件的路径  
  68.     static std::string m_sFilePath;  
  69.     //XML文件是否已经被初始化  
  70.     static bool m_sbIsFilePathInitialized;  
  71. };  
  72.   
  73. NS_CC_END  
  74.   
  75. #endif // __SUPPORT_CCUSERDEFAULT_H__  

CCUserDefault.cpp:

[cpp]  view plain copy
  1. #include "CCUserDefault.h"  
  2. #include "platform/CCCommon.h"  
  3. #include "platform/CCFileUtils.h"  
  4. #include   
  5. #include   
  6.   
  7. // XML的根节点名称  
  8. #define USERDEFAULT_ROOT_NAME    "userDefaultRoot"  
  9. //默认的XML文件名称  
  10. #define XML_FILE_NAME "UserDefault.xml"  
  11. //使用C++标准库的命名空间  
  12. using namespace std;  
  13. //使用Cocos2d命名空间  
  14. NS_CC_BEGIN  
  15. //单例的指针  
  16. static xmlDocPtr g_sharedDoc = NULL;  
  17.   
  18. //静态全局函数,用于取得一个键的XML结点指针  
  19. static xmlNodePtr getXMLNodeForKey(const char* pKey, xmlNodePtr *rootNode)  
  20. {  
  21.     //定义用于存储返回结果的临时指针变量并置空  
  22.     xmlNodePtr curNode = NULL;  
  23.   
  24.     //键值的有效性判断  
  25.     if (! pKey)  
  26.     {  
  27.         return NULL;  
  28.     }  
  29.   
  30.     do   
  31.     {  
  32.         //取得根结点  
  33.         *rootNode = xmlDocGetRootElement(g_sharedDoc);  
  34.         if (NULL == *rootNode)  
  35.         {  
  36.             CCLOG("read root node error");  
  37.             break;  
  38.         }  
  39.   
  40.         //循环查询相应的键结点  
  41.         curNode = (*rootNode)->xmlChildrenNode;  
  42.         while (NULL != curNode)  
  43.         {  
  44.               //如果键结点名称与查询键名称一致中断退出循环  
  45.             if (! xmlStrcmp(curNode->name, BAD_CAST pKey))  
  46.             {  
  47.                 break;  
  48.             }  
  49.              //否则指针指向下一个结点继续循环  
  50.             curNode = curNode->next;  
  51.         }  
  52.     } while (0);  
  53.     //返回结点指针  
  54.     return curNode;  
  55. }  
  56. //取得相应的键值  
  57. static inline const char* getValueForKey(const char* pKey)  
  58. {  
  59.     //定义用于存储返回结果的临时字符指针变量并置空  
  60.     const char* ret = NULL;  
  61.     //定义结点指针变量取得相应的键结点。  
  62.     xmlNodePtr rootNode;  
  63.     xmlNodePtr node = getXMLNodeForKey(pKey, &rootNode);  
  64.   
  65.     // 如果找到了相应的结点,取得结点的内存值转换为字符指针返回。  
  66.     if (node)  
  67.     {  
  68.         ret = (const char*)xmlNodeGetContent(node);  
  69.     }  
  70.   
  71.     return ret;  
  72. }  
  73. //设置相应的键值  
  74. static void setValueForKey(const char* pKey, const char* pValue)  
  75. {  
  76.     xmlNodePtr rootNode;  
  77.     xmlNodePtr node;  
  78.   
  79.     // 有效性判断  
  80.     if (! pKey || ! pValue)  
  81.     {  
  82.         return;  
  83.     }  
  84.   
  85.     // 取得相应的键结点  
  86.     node = getXMLNodeForKey(pKey, &rootNode);  
  87.   
  88.     // 如果找到,设置结点的值为pValue  
  89.     if (node)  
  90.     {  
  91.         xmlNodeSetContent(node, BAD_CAST pValue);  
  92.     }  
  93.     else  
  94.     {  
  95.          //如果找不到键值,则生成相应的键结点和键值结点并放入根结点下。  
  96.         if (rootNode)  
  97.         {  
  98.              //先创建键结点。  
  99.             xmlNodePtr tmpNode = xmlNewNode(NULL, BAD_CAST pKey);  
  100.              //再创建健值结点。  
  101.             xmlNodePtr content = xmlNewText(BAD_CAST pValue);  
  102.              //将键点点放到根结点下。  
  103.             xmlAddChild(rootNode, tmpNode);  
  104.              //将键帧结点放到键结点下。  
  105.             xmlAddChild(tmpNode, content);  
  106.         }      
  107.     }  
  108. }  
  109.   
  110. //初始化单例指针置空  
  111. CCUserDefault* CCUserDefault::m_spUserDefault = 0;  
  112. //初始化XML文件路径为空  
  113. string CCUserDefault::m_sFilePath = string("");  
  114. //初始化文件路径是否被初始化的标记值为false  
  115. bool CCUserDefault::m_sbIsFilePathInitialized = false;  
  116.   
  117. //析构  
  118. CCUserDefault::~CCUserDefault()  
  119. {  
  120.     //将数据写入文件  
  121.     flush();  
  122.     //释放相应的XML文件  
  123.     if (g_sharedDoc)  
  124.     {  
  125.         xmlFreeDoc(g_sharedDoc);  
  126.         g_sharedDoc = NULL;  
  127.     }  
  128.     //单例指针置空  
  129.     m_spUserDefault = NULL;  
  130. }  
  131. //构造  
  132. CCUserDefault::CCUserDefault()  
  133. {  
  134.     //读取相应的XML文件。  
  135.     g_sharedDoc = xmlReadFile(getXMLFilePath().c_str(), "utf-8", XML_PARSE_RECOVER);  
  136. }  
  137. //释放单例  
  138. void CCUserDefault::purgeSharedUserDefault()  
  139. {  
  140.     CC_SAFE_DELETE(m_spUserDefault);  
  141.     m_spUserDefault = NULL;  
  142. }  
  143. //从指定的键中取得布尔值  
  144. bool CCUserDefault::getBoolForKey(const char* pKey)  
  145.  {  
  146.      return getBoolForKey(pKey, false);  
  147.  }  
  148. //从指定的键中取得布尔值,如果没有则返回默认参数。  
  149. bool CCUserDefault::getBoolForKey(const char* pKey, bool defaultValue)  
  150. {  
  151.     const char* value = getValueForKey(pKey);  
  152.     bool ret = defaultValue;  
  153.   
  154.     if (value)  
  155.     {  
  156.         ret = (! strcmp(value, "true"));  
  157.         xmlFree((void*)value);  
  158.     }  
  159.   
  160.     return ret;  
  161. }  
  162. //从指定的键中取得整数值  
  163. int CCUserDefault::getIntegerForKey(const char* pKey)  
  164. {  
  165.     return getIntegerForKey(pKey, 0);  
  166. }  
  167. //从指定的键中取得整数值,如果没有则返回默认参数  
  168. int CCUserDefault::getIntegerForKey(const char* pKey, int defaultValue)  
  169. {  
  170.     const char* value = getValueForKey(pKey);  
  171.     int ret = defaultValue;  
  172.   
  173.     if (value)  
  174.     {  
  175.         ret = atoi(value);  
  176.         xmlFree((void*)value);  
  177.     }  
  178.   
  179.     return ret;  
  180. }  
  181. //从指定的键中取得浮点值  
  182. float CCUserDefault::getFloatForKey(const char* pKey)  
  183. {  
  184.     return getFloatForKey(pKey, 0.0f);  
  185. }  
  186. //从指定的键中取得浮点值,如果没有则返回默认参数。  
  187. float CCUserDefault::getFloatForKey(const char* pKey, float defaultValue)  
  188. {  
  189.     float ret = (float)getDoubleForKey(pKey, (double)defaultValue);  
  190.    
  191.     return ret;  
  192. }  
  193. //从指定的键中取得双精度值  
  194. double  CCUserDefault::getDoubleForKey(const char* pKey)  
  195. {  
  196.     return getDoubleForKey(pKey, 0.0);  
  197. }  
  198. //从指定的键中取得双精度值,如果没有则返回默认参数。  
  199. double CCUserDefault::getDoubleForKey(const char* pKey, double defaultValue)  
  200. {  
  201.     const char* value = getValueForKey(pKey);  
  202.     double ret = defaultValue;  
  203.   
  204.     if (value)  
  205.     {  
  206.         ret = atof(value);  
  207.         xmlFree((void*)value);  
  208.     }  
  209.   
  210.     return ret;  
  211. }  
  212. //从指定的键中取得字符串值  
  213. std::string CCUserDefault::getStringForKey(const char* pKey)  
  214. {  
  215.     return getStringForKey(pKey, "");  
  216. }  
  217. //从指定的键中取得字符串值,如果没有则返回默认参数  
  218. string CCUserDefault::getStringForKey(const char* pKey, const std::string & defaultValue)  
  219. {  
  220.     const char* value = getValueForKey(pKey);  
  221.     string ret = defaultValue;  
  222.   
  223.     if (value)  
  224.     {  
  225.         ret = string(value);  
  226.         xmlFree((void*)value);  
  227.     }  
  228.   
  229.     return ret;  
  230. }  
  231. //设置指定键的布尔值  
  232. void CCUserDefault::setBoolForKey(const char* pKey, bool value)  
  233. {  
  234.     // save bool value as string  
  235.   
  236.     if (true == value)  
  237.     {  
  238.         setStringForKey(pKey, "true");  
  239.     }  
  240.     else  
  241.     {  
  242.         setStringForKey(pKey, "false");  
  243.     }  
  244. }  
  245. //设置指定键的整数值  
  246. void CCUserDefault::setIntegerForKey(const char* pKey, int value)  
  247. {  
  248.     // check key  
  249.     if (! pKey)  
  250.     {  
  251.         return;  
  252.     }  
  253.   
  254.     // format the value  
  255.     char tmp[50];  
  256.     memset(tmp, 0, 50);  
  257.     sprintf(tmp, "%d", value);  
  258.   
  259.     setValueForKey(pKey, tmp);  
  260. }  
  261. //设置指定键的浮点值  
  262. void CCUserDefault::setFloatForKey(const char* pKey, float value)  
  263. {  
  264.     setDoubleForKey(pKey, value);  
  265. }  
  266. //设置指定键的双精度值  
  267. void CCUserDefault::setDoubleForKey(const char* pKey, double value)  
  268. {  
  269.     // check key  
  270.     if (! pKey)  
  271.     {  
  272.         return;  
  273.     }  
  274.   
  275.     // format the value  
  276.     char tmp[50];  
  277.     memset(tmp, 0, 50);  
  278.     sprintf(tmp, "%f", value);  
  279.   
  280.     setValueForKey(pKey, tmp);  
  281. }  
  282. //设置指定键的字符串值  
  283. void CCUserDefault::setStringForKey(const char* pKey, const std::string & value)  
  284. {  
  285.     // check key  
  286.     if (! pKey)  
  287.     {  
  288.         return;  
  289.     }  
  290.   
  291.     setValueForKey(pKey, value.c_str());  
  292. }  
  293. //取得单例  
  294. CCUserDefault* CCUserDefault::sharedUserDefault()  
  295. {  
  296.     //初始化XML文件  
  297.     initXMLFilePath();  
  298.   
  299.     //如果文件不存在则创建,如果创建不成功返回失败。  
  300.     if ((! isXMLFileExist()) && (! createXMLFile()))  
  301.     {  
  302.         return NULL;  
  303.     }  
  304.     //如果当前单例指针为空,创建单例  
  305.     if (! m_spUserDefault)  
  306.     {  
  307.         m_spUserDefault = new CCUserDefault();  
  308.     }  
  309.     //返回单例指针  
  310.     return m_spUserDefault;  
  311. }  
  312. //XML文件是否存在。  
  313. bool CCUserDefault::isXMLFileExist()  
  314. {  
  315.     //创建一个文件指针打开相应的文件。  
  316.     FILE *fp = fopen(m_sFilePath.c_str(), "r");  
  317.     bool bRet = false;  
  318.     //看是否能打开以判断是否存在。  
  319.     if (fp)  
  320.     {  
  321.         bRet = true;  
  322.         fclose(fp);  
  323.     }  
  324.   
  325.     return bRet;  
  326. }  
  327. //初始化XML文件路径  
  328. void CCUserDefault::initXMLFilePath()  
  329. {  
  330.     //如果初始化的标记为false,组合出文件字符串。  
  331.     if (! m_sbIsFilePathInitialized)  
  332.     {  
  333.         //文件路径名为文件系统的写入路径[后面详解]下的“UserDefault.xml”。  
  334.         m_sFilePath += CCFileUtils::sharedFileUtils()->getWriteablePath() + XML_FILE_NAME;  
  335.         m_sbIsFilePathInitialized = true;  
  336.     }      
  337. }  
  338.   
  339. //创建XML文件  
  340. bool CCUserDefault::createXMLFile()  
  341. {  
  342.     bool bRet = false;  
  343.     //定义临时的XML文档指针  
  344.     xmlDocPtr doc = NULL;  
  345.     //使用do-while框架结构来随时中断  
  346.     do   
  347.     {  
  348.         // 创建一个新的1.0版的XML文档  
  349.         doc = xmlNewDoc(BAD_CAST"1.0");  
  350.         if (doc == NULL)  
  351.         {  
  352.             CCLOG("can not create xml doc");  
  353.             break;  
  354.         }  
  355.   
  356.         // 创建根结点  
  357.         xmlNodePtr rootNode = xmlNewNode(NULL, BAD_CAST USERDEFAULT_ROOT_NAME);  
  358.         if (rootNode == NULL)  
  359.         {  
  360.             CCLOG("can not create root node");  
  361.             break;  
  362.         }  
  363.   
  364.         //设置创建的结点为XML文档中的根结点  
  365.         xmlDocSetRootElement(doc, rootNode);  
  366.   
  367.         //保存XML文件  
  368.         xmlSaveFile(m_sFilePath.c_str(), doc);  
  369.   
  370.         bRet = true;  
  371.     } while (0);  
  372.   
  373.     // 释放文档指针  
  374.     if (doc)  
  375.     {  
  376.         xmlFreeDoc(doc);  
  377.     }  
  378.     //返回成败  
  379.     return bRet;  
  380. }  
  381. //取得XML文件路径  
  382. const string& CCUserDefault::getXMLFilePath()  
  383. {  
  384.     return m_sFilePath;  
  385. }  
  386. //立即将XML数据写入文件  
  387. void CCUserDefault::flush()  
  388. {  
  389.     // 如果文档有效则进行保存文档到文件中。  
  390.     if (g_sharedDoc)  
  391.     {  
  392.         xmlSaveFile(CCUserDefault::sharedUserDefault()->getXMLFilePath().c_str(), g_sharedDoc);  
  393.     }  
  394. }  
  395.   
  396. NS_CC_END  

              这引CCUserDefault类写的真是不错。非常简洁好用。但我们要明白“文件系统的写入路径”是什么?

              在CCFileUtils.cpp中找到相应的函数:

//取得文件写入路径

[cpp]  view plain copy
  1. string CCFileUtils::getWriteablePath()  
  2. {  
  3.     // 取得当前程序所在目录  
  4.     char full_path[_MAX_PATH + 1];  
  5.     ::GetModuleFileNameA(NULL, full_path, _MAX_PATH + 1);  
  6.   
  7.     // 如果是Release模式  
  8. #ifndef _DEBUG  
  9.         // 取得移除路径的文件名  
  10.         char *base_name = strrchr(full_path, '\\');  
  11.   
  12.         if(base_name)  
  13.         {  
  14.             char app_data_path[_MAX_PATH + 1];  
  15.   
  16.             // 取得系统文件夹应用程序数据目录,如C:\Documents and Settings\username\Local Settings\Application Data,可参看: http://wenku.baidu.com/view/412cfc02f78a6529647d53e5.html  
  17.   
  18.             if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, app_data_path)))  
  19.             {  
  20.                 //创建字符串ret存放取出的路径  
  21.                 string ret((char*)app_data_path);  
  22.   
  23.                 //字符串尾部加上文件名。  
  24.                 ret += base_name;  
  25.   
  26.                 // 去除扩展名并加上”\\”  
  27.                 ret = ret.substr(0, ret.rfind("."));  
  28.                 ret += "\\";  
  29.   
  30.                 // 创建相应的目录  
  31.                 if (SUCCEEDED(SHCreateDirectoryExA(NULL, ret.c_str(), NULL)))  
  32.                 {  
  33.                     //如果成功返回ret。  
  34.                     return ret;  
  35.                 }  
  36.             }  
  37.         }  
  38. #endif // not defined _DEBUG  
  39.   
  40.     //创建字符串ret存放当前程序所在目录。  
  41.     string ret((char*)full_path);  
  42.   
  43.     // 截取带”\\”部分的路径。  
  44.     ret =  ret.substr(0, ret.rfind("\\") + 1);  
  45.     //返回ret。  
  46.     return ret;  
  47. }  

 

              这个函数对于DEBUG和RELEASE模式有区别处理,DEBUG模式取出的路径即为当前程序所在目录,RELEASE模式则在系统目录下创建当前程序名称的目录并返回。

 

              接下来我们看一下Cocos2d-x在例子中的具体使用,找到TestCpp中的UserDefaultTest。

UserDefaultTest.h:

[cpp]  view plain copy
  1. "font-size:14px;">#ifndef _USERDEFAULT_TEST_H_  
  2. #define _USERDEFAULT_TEST_H_  
  3.   
  4. #include "cocos2d.h"  
  5. #include "../testBasic.h"  
  6. //创建一个层用于处理XML数据  
  7. class UserDefaultTest : public CCLayer  
  8. {  
  9. public:  
  10.     UserDefaultTest();  
  11.     ~UserDefaultTest();  
  12.   
  13. private:  
  14.     void doTest();  
  15. };  
  16. //演示用的场景  
  17. class UserDefaultTestScene : public TestScene  
  18. {  
  19. public:  
  20.     virtual void runThisTest();  
  21. };  
  22. #endif // _USERDEFAULT_TEST_H_  
  23.   

对应的CPP:

[cpp]  view plain copy
  1. // 开启COCOS2D的DEBUG标记  
  2. #define COCOS2D_DEBUG 1  
  3. #include "UserDefaultTest.h"  
  4. #include "stdio.h"  
  5. #include "stdlib.h"  
  6. //层的构造函数。  
  7. UserDefaultTest::UserDefaultTest()  
  8. {  
  9.     //取得屏幕大小,创建文字标签提示。  
  10.     CCSize s = CCDirector::sharedDirector()->getWinSize();  
  11. CCLabelTTF* label = CCLabelTTF::create("CCUserDefault test see log""Arial", 28);  
  12. //将标签放到当前层中并置于屏幕中央。  
  13.     addChild(label, 0);  
  14.     label->setPosition( ccp(s.width/2, s.height-50) );  
  15.     //调用测试函数。  
  16.     doTest();  
  17. }  
  18.   
  19. void UserDefaultTest::doTest()  
  20. {  
  21.     //开始打印日志。  
  22.     CCLOG("********************** init value ***********************");  
  23.   
  24.     // 创建CCUserDefault单例并创建相应的数据类型键,设置其键值。  
  25.   
  26.     CCUserDefault::sharedUserDefault()->setStringForKey("string""value1");  
  27.     CCUserDefault::sharedUserDefault()->setIntegerForKey("integer", 10);  
  28.     CCUserDefault::sharedUserDefault()->setFloatForKey("float", 2.3f);  
  29.     CCUserDefault::sharedUserDefault()->setDoubleForKey("double", 2.4);  
  30.     CCUserDefault::sharedUserDefault()->setBoolForKey("bool"true);  
  31.   
  32.     // 设置完后,打印各类型键取出的值。  
  33.     string ret = CCUserDefault::sharedUserDefault()->getStringForKey("string");  
  34.     CCLOG("string is %s", ret.c_str());  
  35.   
  36.     double d = CCUserDefault::sharedUserDefault()->getDoubleForKey("double");  
  37.     CCLOG("double is %f", d);  
  38.   
  39.     int i = CCUserDefault::sharedUserDefault()->getIntegerForKey("integer");  
  40.     CCLOG("integer is %d", i);  
  41.   
  42.     float f = CCUserDefault::sharedUserDefault()->getFloatForKey("float");  
  43.     CCLOG("float is %f", f);  
  44.   
  45.     bool b = CCUserDefault::sharedUserDefault()->getBoolForKey("bool");  
  46.     if (b)  
  47.     {  
  48.         CCLOG("bool is true");  
  49.     }  
  50.     else  
  51.     {  
  52.         CCLOG("bool is false");  
  53.     }  
  54.       
  55.     //CCUserDefault::sharedUserDefault()->flush();  
  56.     CCLOG("********************** after change value ***********************");  
  57.   
  58.     // 改变相应键的键值。  
  59.   
  60.     CCUserDefault::sharedUserDefault()->setStringForKey("string""value2");  
  61.     CCUserDefault::sharedUserDefault()->setIntegerForKey("integer", 11);  
  62.     CCUserDefault::sharedUserDefault()->setFloatForKey("float", 2.5f);  
  63.     CCUserDefault::sharedUserDefault()->setDoubleForKey("double", 2.6);  
  64.     CCUserDefault::sharedUserDefault()->setBoolForKey("bool"false);  
  65.   
  66.     //将XML数据保存到相应文件中。  
  67.     CCUserDefault::sharedUserDefault()->flush();  
  68.   
  69.     // 再次打印各键值。  
  70.   
  71.     ret = CCUserDefault::sharedUserDefault()->getStringForKey("string");  
  72.     CCLOG("string is %s", ret.c_str());  
  73.   
  74.     d = CCUserDefault::sharedUserDefault()->getDoubleForKey("double");  
  75.     CCLOG("double is %f", d);  
  76.   
  77.     i = CCUserDefault::sharedUserDefault()->getIntegerForKey("integer");  
  78.     CCLOG("integer is %d", i);  
  79.   
  80.     f = CCUserDefault::sharedUserDefault()->getFloatForKey("float");  
  81.     CCLOG("float is %f", f);  
  82.   
  83.     b = CCUserDefault::sharedUserDefault()->getBoolForKey("bool");  
  84.     if (b)  
  85.     {  
  86.         CCLOG("bool is true");  
  87.     }  
  88.     else  
  89.     {  
  90.         CCLOG("bool is false");  
  91.     }  
  92. }  
  93.   
  94. //析构  
  95. UserDefaultTest::~UserDefaultTest()  
  96. {  
  97. }  
  98. //场景启动时调用。  
  99. void UserDefaultTestScene::runThisTest()  
  100. {  
  101.     //创建一个演示用的层并放到当前演示场景中。  
  102.     CCLayer* pLayer = new UserDefaultTest();  
  103.     addChild(pLayer);  
  104.     //启动当前场景。  
  105.     CCDirector::sharedDirector()->replaceScene(this);  
  106.     pLayer->release();  
  107. }  

当我们在DEBUG模式下运行此演示后程序截图为:



在程序的运行目录会出现:



              用IE打开后可以看到相应的键值数据。这样我们便学会了如何存储游戏中用到的数据到XML文件中。下课!

你可能感兴趣的:(Cocos2d-x 深入解析系列 : 以XML文件方式保存用户数据)