zoukankan      html  css  js  c++  java
  • 特效编辑器开发手记2——cocos2dx粒子系统的plist文件 深圳

    粒子编辑器必须要有一个保存粒子文件的功能,cocos2d-x使用plist来保存粒子文件(这是苹果的一种基于xml的文件格式,也适用于动画等)
    于是我查看了cocos2d-x里面加载plist文件的代码,它是先把plist加载到一个CCDictionary类中,然后在这个类里面方便地通过key-value来获取相应的信息
     
     1 CCParticleSystem.cpp
     2     m_sPlistFile = CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(plistFile);
     3     CCDictionary *dict = CCDictionary::createWithContentsOfFileThreadSafe(m_sPlistFile.c_str());
     4  
     5 CCDictionary.cpp
     6 CCDictionary* CCDictionary::createWithContentsOfFileThreadSafe(const char *pFileName)
     7 {
     8     return ccFileUtils_dictionaryWithContentsOfFileThreadSafe(pFileName);
     9 }
    10  
    11 CCFileUtilsCommon_cpp.h
    12 CCDictionary* ccFileUtils_dictionaryWithContentsOfFileThreadSafe(const char *pFileName)
    13 {
    14     CCDictMaker tMaker;
    15     return tMaker.dictionaryWithContentsOfFile(pFileName);
    16 }
    17  
    18 CCFileUtilsCommon_cpp.h
    19     CCDictionary* dictionaryWithContentsOfFile(const char *pFileName)
    20     {
    21         m_eResultType = SAX_RESULT_DICT;
    22         CCSAXParser parser;
    23  
    24         if (false == parser.init("UTF-8"))
    25         {
    26             return NULL;
    27         }
    28         parser.setDelegator(this);
    29  
    30         parser.parse(pFileName);
    31         return m_pRootDict;
    32     }
    33  
    34  
    35 bool CCSAXParser::parse(const char *pszFile)
    36 {
    37     bool bRet = false;
    38     unsigned long size = 0;
    39     char* pBuffer = (char*)CCFileUtils::sharedFileUtils()->getFileData(pszFile, "rt", &size);
    40     if (pBuffer != NULL && size > 0)
    41     {
    42         bRet = parse(pBuffer, size);
    43     }
    44     CC_SAFE_DELETE_ARRAY(pBuffer);
    45     return bRet;
    46 }
    47  
    48  
    49 bool CCSAXParser::parse(const char* pXMLData, unsigned int uDataLength)
    50 {
    51     /*
    52      * this initialize the library and check potential ABI mismatches
    53      * between the version it was compiled for and the actual shared
    54      * library used.
    55      */
    56     LIBXML_TEST_VERSION
    57     xmlSAXHandler saxHandler;
    58     memset( &saxHandler, 0, sizeof(saxHandler) );
    59     // Using xmlSAXVersion( &saxHandler, 2 ) generate crash as it sets plenty of other pointers...
    60     saxHandler.initialized = XML_SAX2_MAGIC;  // so we do this to force parsing as SAX2.
    61     saxHandler.startElement = &CCSAXParser::startElement;
    62     saxHandler.endElement = &CCSAXParser::endElement;
    63     saxHandler.characters = &CCSAXParser::textHandler;
    64     
    65     int result = xmlSAXUserParseMemory( &saxHandler, this, pXMLData, uDataLength );
    66     if ( result != 0 )
    67     {
    68         return false;
    69     }
    70     /*
    71      * Cleanup function for the XML library.
    72      */
    73     xmlCleanupParser();
    74     /*
    75      * this is to debug memory for regression tests
    76      */
    77 #if (CC_TARGET_PLATFORM != CC_PLATFORM_BADA)
    78     xmlMemoryDump();
    79 #endif
    80     
    81     return true;
    82 }
     
    通过上面的代码可以看到,CCDictMaker通过调用CCSAXParser 这个类来进行plist文件的读取和解析,也就是 parse函数,然后生成一个CCDictionary
    通过CCSAXParser 自己的startElement和endElement来对plist进行解析,然后插入到CCDictionary的哈希中,上层调用valueforkey即可获取对应的值
    但说了这么多,我们如何保存呢?cocos2d-x提供了怎样的接口给我们进行保存呢?
     
    查阅CCDictionary这个类,发现与valueforkey有那么点对应关系的,也就setObject这个函数,但这个函数只是把Object插入到CCDictionary本身的哈希中而已,并没有保存到plist,所以这里CCDictionary这个类跟plist唯一的联系仅仅只是从plist中解析,获取数据而已。
     
    那么我们只能把目光转移到生成CCDictionary的CCDictMaker 这个类来了,CCDictionary 是由CCDictMaker调用CCSAXParser 生成的,那么CCDictMaker 可有提供保存到plist的方法?答案还是没有!
     
    最后到了CCSAXParser这个类,只能看到,他调用xmlSAXUserParseMemory函数来将plist文件加载进来,至于xmlSAXUserParseMemory函数,那是在libxml/parser.h这个头文件中。
     
    随后又查看了大量代码,从头到尾都没有保存plist文件的代码,至于CCUserDefault这个类,仅仅只是将数据保存在一个默认的xml文件中。
     
    到了这里,也就不指望cocos提供什么接口了,直接查看粒子系统的plist文件,然后,根据其格式,自己实现一个plist类,用来保存粒子系统到plist文件。
     
    plist文件格式大致如下,第一行是xml头,包含xml版本和字符编码
    第二行是文档类型,"-//Apple//DTD PLIST 1.0//EN"是它的pubid "http://www.apple.com/DTDs/PropertyList-1.0.dtd"是它的sysid
    第三行是plist的根节点,有version属性,下面有一个子节点dict,该子节点下面存放粒子系统的所有属性值
    每个值由两个节点来表示,一个key节点,紧跟着还有一个value节点来表这个key的值,value节点有以下几种类型:<real>表示浮点数,<integer>表示整型,<string>表示字符串,<array>表示数组
     
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
    <key>angle</key>
    <real>270</real>
    <key>angleVariance</key>
    <real>0.0</real>
    ......
    </dict>
    </plist>
     
    关于xml的操作,之前用过CMarkUpSTL,tinyxml,这两个用得比较熟,但cocos用的是libxml,也只能去学习一下libxml
    这是官网地址http://www.xmlsoft.org/
    还有相关example的地址http://www.xmlsoft.org/examples/testWriter.c
    在项目中实现一段如下的测试代码来保存plist
     
     1 //创建test.plist文件
     2 m_Writer = xmlNewTextWriterFilename(plist, 0);
     3  
     4 //设置编码为utf-8并开始文档
     5 xmlTextWriterStartDocument(m_Writer, NULL, "UTF-8", NULL);
     6 //设置文档类型
     7 xmlTextWriterWriteDTD(m_Writer, BAD_CAST "plist", BAD_CAST "-//Apple//DTD PLIST 1.0//EN", BAD_CAST "http://www.apple.com/DTDs/PropertyList-1.0.dtd", NULL);
     8 //根节点为plist,version属性为1.0
     9 xmlTextWriterStartElement(m_Writer, BAD_CAST "plist");
    10 xmlTextWriterWriteAttribute(m_Writer, BAD_CAST "version", BAD_CAST "1.0");
    11 
    12 //dict节点
    13 xmlTextWriterStartElement(m_Writer, BAD_CAST "dict");
    14  
    15 //写入测试数据
    16 xmlTextWriterWriteElement(m_Writer, BAD_CAST "key", BAD_CAST "key1");
    17 xmlTextWriterWriteElement(m_Writer, BAD_CAST "real", BAD_CAST "key1");
    18  
    19 //写入Base64数据
    20 xmlTextWriterStartElement(m_Writer, BAD_CAST "Texture");
    21 xmlTextWriterWriteBase64(m_Writer, "abcdefghij", 0, 12);
    22 xmlTextWriterEndElement(m_Writer);
    23  
    24 //结束并保存
    25 xmlTextWriterEndDocument(m_Writer);
     
    查看保存后的plist文件,发现内容是正确的,但既无缩进,又无回车,所有的代码都被写在一行,难看之极,谷歌之,需要在打开文档之前加入xmlKeepBlanksDefault(0);加了进去也毫无效果,那便算了,反正plist文件一般也是只用不看,有时间看一下libxml的源码再研究下吧
  • 相关阅读:
    java实现第七届蓝桥杯方格填数
    java实现第七届蓝桥杯方格填数
    Java实现第八届蓝桥杯正则问题
    Java实现第八届蓝桥杯正则问题
    手把手教你用Mysql-Cluster-7.5搭建数据库集群
    MySQL集群---②Windows平台搭建MySQL CLUSTER集群
    mysql集群搭建教程-基础篇
    Mysql多实例的配置和管理
    MySQL 使用mysqld_multi部署单机多实例详细过程
    [MySQL 5.1 体验]MySQL 实例管理器 mysqlmanager 初试
  • 原文地址:https://www.cnblogs.com/ybgame/p/2606107.html
Copyright © 2011-2022 走看看