- 精通Cocos2d-x游戲開發(進階卷)
- 王永寶
- 967字
- 2020-11-28 22:36:56
1.3 讀寫Plist文件
Plist是Apple公司提供的一種格式,只在iOS系統下使用,但Cocos2d-x將其發揚光大了,Plist是一種XML格式,所以XML存在的問題,它也存在。對于Plist而言,Cocos2d-x已經將接口封裝好了,唯一存在的平臺差異性問題,就是在iOS下的Dictionary和Windows/Android下的有些不同,在你遍歷一個iOS下的字典時,是無序的,字典結構本身也是無序的,而在Windows/Android下,CCDictionary是Cocos2d-x自己實現的,在遍歷的時候,字典里面的每一項,跟你的Plist文件里每一項的順序是一致的。所以,你的代碼不要依賴于字典的順序。因為最恐怖的事情不是代碼通不過,而是代碼有時候可以通過,有時候又通不過。
Cocos2d-x里的粒子系統、動畫、圖集等大多都用到了Plist,粒子編輯器、拼圖工具、動畫編輯器等都可以直接導出Plist格式的文件,其中粒子格式比較特殊的一點是將粒子圖片也直接放到Plist文件里了,因為粒子圖片一般都比較小,放到一起管理起來非常方便。
1.3.1 Plist格式簡介
Plist里面有一些特有的結構,主要包含以下標簽。
? <string>:UTF-8字符串。
? <real>、<integer>:十進制的數字字符串。
? <true/>、<false />:真和假。
? <date>:日期字符串(ISO8601格式,例如2013-11-3)。
? <data>:Base64編碼的數據。
? <array>:任意長度的數組。
? <dict>:key-value格式的字典,key是<key>標簽,value可以是任意格式。
可以用Notepad++或者plist Editor之類的軟件來編輯Plist文件,下面是一個粒子系統的Plist文件的一部分內容,我們可以看到和普通的XML文件不同的是,Plist文件多了一個DTD字段用于描述這個文件,而且標簽的名字并不是隨意的,基本由上面列出的標簽組成,根節點是一個名為plist的節點。
<?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>a</key> <string>string</string> <key>b</key> <false/> <key>c</key> <integer>123</integer> <key>d</key> <real>0.2500000</real> <key>e</key> <dict> <key>a</key> <string>string</string> <key>b</key> <false/> <key>c</key> <integer>123</integer> <key>d</key> <real>0.2500000</real> </dict> </dict> </plist>
1.3.2 讀寫Plist文件
在Cocos2d-x中讀取一個Plist文件是一件非常簡單的事情,通過FileUtils單例的一些方法直接從Plist文件中加載并創建ValueVector和ValueMap等容器,但是要加載的Plist文件的plist節點下必須是dict或者array節點。
//傳入Plist文件名,解析后返回一個ValueMap對象 virtual ValueMap getValueMapFromFile(const std::string& filename); //傳入Plist文件名,解析后返回一個ValueVector對象 virtual ValueVector getValueVectorFromFile(const std::string& filename);
下面介紹一下Plist文件的讀取,通過FileUtils的getValueMapFromFile()方法將Plist文件解析成ValueMap并返回,然后調用自定義的dumpValueMap()方法,將容器的內容打印出來。
string plistFile = FileUtils::getInstance()->getWritablePath() + "myplist. plist"; ValueMap dict = FileUtils::getInstance()->getValueMapFromFile(plistFile); dumpValueMap(dict);
dumpValueMap()方法會遍歷傳入的ValueMap對象,根據對象的類型進行打印,dumpValueMap的實現如下。
void dumpValueMap(ValueMap& vm) { //根據對象類型打印對象值 for (auto& item : vm) { switch (item.second.getType()) { case Value::Type::BOOLEAN: CCLOG("%s is %d", item.first.c_str(), item.second.asBool()); break; case Value::Type::INTEGER: CCLOG("%s is %d", item.first.c_str(), item.second.asInt()); break; case Value::Type::STRING: CCLOG("%s is %s", item.first.c_str(), item.second.asString(). c_str()); break; case Value::Type::FLOAT: case Value::Type::DOUBLE: CCLOG("%s is %f", item.first.c_str(), item.second.asFloat()); break; case Value::Type::MAP: CCLOG("========== %s is ValueMap ==========", item.first.c_str()); dumpValueMap(item.second.asValueMap()); CCLOG("===================================="); } } }
除了讀取Plist文件之外,FileUtils還提供了寫入Plist文件的接口,通過FileUtils的writeValueMapToFile()方法可以將一個ValueMap序列化到指定的文件中。
ValueMap dict; dict.insert(pair<string, Value>(string("a"), Value("string"))); dict.insert(pair<string, Value>(string("b"), Value(false))); dict.insert(pair<string, Value>(string("c"), Value(123))); dict.insert(pair<string, Value>(string("d"), Value(0.25f))); dict.insert(pair<string, Value>(string("e"), Value(dict))); string plistFile = FileUtils::getInstance()->getWritablePath() + "myplist. plist"; if (FileUtils::getInstance()->writeValueMapToFile(dict, plistFile)) { CCLOG("write plist %s success", plistFile.c_str()); }