小for的Cocos2d-x学习笔记与感悟11之文件保存和中文显示

来源:互联网 发布:ray kurzweil 骗 知乎 编辑:程序博客网 时间:2024/05/01 09:28

本文小for原创,转载请注明出处。

在这一节中,小for会记录简单的文件保存数据和中文的显示。Cocos2d-x和Android一样,都在处理xml文件上很完善。这一节中,小for只学习xml最基本的操作,文件内容保存在Cocos2d-x为我们提供的UserDefault.xml文件中。其实,这个文件已经可以满足简单的排行榜、分数、角色信息等的保存,但是,如果一个游戏有爱太复杂的话,我们还是应该建立自己的文件或者数据库来保存数据。除了使用xml,我们也可以尝试使用txt文件来保存文件,这种方法可以使用C++的文件操作来完成,但是不知道在真机上能不能编译通过(vs2010的Cocos2d-x模拟器上能通过)。

Cocos2d-x为我们提供了CCUserDefault类来完成数据在UserDefault.xml上的操作。这个类的操作是非常简单的,我们暂时不关注它的具体实现,打开CCUserDefault.h文件可以看到它的全部操作方法,而且简单易懂。

#ifndef __SUPPORT_CCUSERDEFAULT_H__#define __SUPPORT_CCUSERDEFAULT_H__ #include "platform/CCPlatformMacros.h"#include <string> NS_CC_BEGIN /** * @addtogroup data_storage * @{ */ /** * CCUserDefault acts as a tiny database. You can save and get base type values by it. * For example, setBoolForKey("played", true) will add a bool value true into the database. * Its key is "played". You can get the value of the key by getBoolForKey("played"). *  * It supports the following base types: * bool, int, float, double, string */class CC_DLL CCUserDefault{public:    ~CCUserDefault();     // get value methods     /**    @brief Get bool value by key, if the key doesn't exist, a default value will return.     You can set the default value, or it is false.    */    bool    getBoolForKey(const char* pKey, bool defaultValue = false);    /**    @brief Get integer value by key, if the key doesn't exist, a default value will return.     You can set the default value, or it is 0.    */    int        getIntegerForKey(const char* pKey, int defaultValue = 0);    /**    @brief Get float value by key, if the key doesn't exist, a default value will return.     You can set the default value, or it is 0.0f.    */    float    getFloatForKey(const char* pKey, float defaultValue=0.0f);    /**    @brief Get double value by key, if the key doesn't exist, a default value will return.     You can set the default value, or it is 0.0.    */    double  getDoubleForKey(const char* pKey, double defaultValue=0.0);    /**    @brief Get string value by key, if the key doesn't exist, a default value will return.    You can set the default value, or it is "".    */    std::string getStringForKey(const char* pKey, const std::string & defaultValue = "");     // set value methods     /**    @brief Set bool value by key.    */    void    setBoolForKey(const char* pKey, bool value);    /**    @brief Set integer value by key.    */    void    setIntegerForKey(const char* pKey, int value);    /**    @brief Set float value by key.    */    void    setFloatForKey(const char* pKey, float value);    /**    @brief Set double value by key.    */    void    setDoubleForKey(const char* pKey, double value);    /**    @brief Set string value by key.    */    void    setStringForKey(const char* pKey, const std::string & value);    /**     @brief Save content to xml file     */    void    flush();     static CCUserDefault* sharedUserDefault();    static void purgeSharedUserDefault();    const static std::string& getXMLFilePath(); private:    CCUserDefault();    static bool createXMLFile();    static bool isXMLFileExist();    static void initXMLFilePath();        static CCUserDefault* m_spUserDefault;    static std::string m_sFilePath;    static bool m_sbIsFilePathInitialized;};


 

几乎所以提供的方法都使用get和set来命名,例如setStringForKey显然是根据key来设置string的内容。

下面是简单的存入数据的操作(是我们写的代码内容了,上面是阅读的^-^)

 

CCUserDefault::sharedUserDefault()->setStringForKey("String", "my string");CCUserDefault::sharedUserDefault()->setIntegerForKey("Int",10);CCUserDefault::sharedUserDefault()->setBoolForKey("bool",true);CCUserDefault::sharedUserDefault()->setFloatForKey("float",1.56f);


 

这段运行结束后,UserDefault.xml中内容是

<?xmlversion="1.0"encoding="utf-8"?><userDefaultRoot>  <String>my string</String>  <Int>10</Int>  <bool>true</bool>  <float>1.560000</float></userDefaultRoot>


 

显然,我们需要保存的内容已经存进去了。接下来,我们在将内容读出来,这里只以获取String为例。

string str=CCUserDefault::sharedUserDefault()->getStringForKey("String");

哇,就这样简单。

然而,我们通常不会保存英文(至少国内游戏很少),我们尝试来保存一下中文,将上述setStringForKey的值写成

CCUserDefault::sharedUserDefault()->setStringForKey("String", "中文测试");

运行一遍后,我们发现文件中的String字段是乱码:

<?xmlversion="1.0"encoding="utf-8"?><userDefaultRoot>  <String>���IJ���</String>  <Int>10</Int>  <bool>true</bool>  <float>1.560000</float></userDefaultRoot>

(黑黢黢的乱码。)网上其实有很多解决Cocos2d-x显示中文出现乱码问题的文章,小for也是参考了别人的文章才解决问题的,这里直接贴出别人写好的函数,并在下面记录这个方法的使用方法。

实现方法

 

         std::string WideByte2UTF8(const wstring& text)         {                   int asciisize = ::WideCharToMultiByte(CP_UTF8, 0, text.c_str(), text.size(), NULL, 0, NULL, NULL);                   if (asciisize == ERROR_NO_UNICODE_TRANSLATION ||asciisize == 0)                     {                              return string();                   }                   char* resultstring = new char[asciisize];                   int convresult = ::WideCharToMultiByte(CP_UTF8, 0, text.c_str(), text.size(), resultstring, asciisize, NULL, NULL);                   if (convresult != asciisize)                   {                             return string();                   }                   std::string buffer(resultstring, convresult);                   delete[] resultstring;                   return buffer;         }

再度声明,这个方法不是小for写的,如果侵犯了该大牛的权益,请提醒我删除。(开源~)

这个方法使用简单:

std::string text = WideByte2UTF8(L"你好世界”);

当然,要把这个转码后的text显示在屏幕上,还需要将text转成char*。

const char* chs=text.c_str();

之后,可以把这个chs直接放入文件保存,或者通过CCLabelTTF控件显示出来。下面截图展示了中文保存和显示的成功。

这个方法虽然多了一个步骤,但是的确解决了这个问题,官方看来也没想法要解决这问题,不过,我们已经不担心了,是不是?

 

 

正文结束,闲聊时间~

其实虽然小for的选课是C++,但是以前却是做Java得更多,因此对C++其实并不了解,有时还得查询常用的方法。小for私底下觉得C++的确没有Java好用,现在发现的主要是在Exception处理和string的操作。特别是Exception,小for觉得Java简直处理完了,程序猿几乎不考虑,直接try-catch。

一直以为大三课比较少,现在一看才知道,太坑爹了……

 

小for邮箱:xujianflying@sohu.com

欢迎学习交流,批评指正!

原创粉丝点击