本站文章均為 李華明Himi 原創,轉載務必在明顯處註明:(作者新浪微博: @李華明Himi ) 轉載自【黑米GameDev街區】原文連結: http://www.himigame.com/iphone-cocos2dx/653.html ☞ 點擊訂閱 ☜ 本部落格最新動向!及時將最新博文通知您!
分享
本篇跟大家分享下Cocos2dX中的儲存,其中也介紹些細節容易犯錯的問題;
在Cocos2dX中提供了內建儲存類:CCUserDefault ,當然了這裡Himi強調一點,如果你的資料量比較大,建議使用SQL儲存比較適合,另外一點要注意的是,儘可能不要在Cocos2dX中使用與平台相關的api進行開發,例如Xcode使用Cocos2dX進行開發遊戲時不小心使用了iOS的控制項/組件在項目中,那麼當移植到Android等平台的時候就肯定異常費勁,估計連正常運行都不可能,因為其他平台不可能正好有iOS的這些控制項,即使有也肯定底層實現不一樣!換句話而言,神馬功能都使用Cocos2dX api實現,盡量都向X靠攏吧,所以這裡的儲存我也使用X內建的CCUserDefault;至少使用Cocos2dX內建的對於跨平台這一塊肯定支援的比較好啦;
言歸正傳,先大致介紹一下這個類的API:
123456789101112131415161718192021222324252627282930 |
Public Member Functions ~CCUserDefault () bool getBoolForKey ( const char *pKey, bool defaultValue= false ) Get bool value by key, if the key doesn't exist, a default value will return . int getIntegerForKey ( const char *pKey, int defaultValue=0) Get integer value by key, if the key doesn't exist, a default value will return . float getFloatForKey ( const char *pKey, float defaultValue=0.0f) Get float value by key, if the key doesn't exist, a default value will return . double getDoubleForKey ( const char *pKey, double defaultValue=0.0) Get double value by key, if the key doesn't exist, a default value will return . std::string getStringForKey ( const char *pKey, const std::string &defaultValue= "" ) Get string value by key, if the key doesn't exist, a default value will return . void setBoolForKey ( const char *pKey, bool value) Set bool value by key. void setIntegerForKey ( const char *pKey, int value) Set integer value by key. void setFloatForKey ( const char *pKey, float value) Set float value by key. void setDoubleForKey ( const char *pKey, double value) Set double value by key. void setStringForKey ( const char *pKey, const std::string &value) Set string value by key. void flush () Save content to xml file. Static Public Member Functions static CCUserDefault * sharedUserDefault () static void purgeSharedUserDefault () static const std::string & getXMLFilePath () |
從以上可以一目瞭然CCUserDefault的使用和功能,雜湊表結構,Key -Value,key索引Value值;
提供的儲存都是些基礎類型,bool,int,string,double,float,方法很容易懂:儲存使用set ,擷取使用get !
那麼最後static方法中可以看到CCUserDefault類留出了一個sharedUserDefault作為介面供開發人員使用,那麼大概介紹後,下面我們來寫幾段代碼驗證下:
12345678 |
//我們這裡簡單儲存條資料 CCUserDefault::sharedUserDefault()->setStringForKey( "key" , "himi" ); CCUserDefault::sharedUserDefault()->flush(); //這裡一定要提交寫入哦,否則不會記錄到xml中,下次啟動遊戲你就擷取不到value了。 //這裡隨便定義一個string為了驗證我們的儲存 string str= "wahaha" ; //取出我們剛儲存的himi,然後賦值給str驗證下; str= CCUserDefault::sharedUserDefault()->getStringForKey( "key" ); CCLog( "列印str=:%s" ,str.c_str()); |
這裡要注意, CCUserDefault中有個 flush()的函數,這個用來將資料寫入xml檔案中,也就是說當你使用setXX的一些函數後記得提交(調用一下flush函數)
OK,下面是控制台輸入的結果:
12345678910111213 |
Cocos2d: cocos2d: cocos2d-1.0.1-x-0.12.0 Cocos2d: cocos2d: GL_VENDOR: Imagination Technologies Cocos2d: cocos2d: GL_RENDERER: PowerVR SGX 543 Cocos2d: cocos2d: GL_VERSION: OpenGL ES-CM 1.1 IMGSGX543-63.14.2 Cocos2d: cocos2d: GL_MAX_TEXTURE_SIZE: 4096 Cocos2d: cocos2d: GL_MAX_MODELVIEW_STACK_DEPTH: 16 Cocos2d: cocos2d: GL supports PVRTC: YES Cocos2d: cocos2d: GL supports BGRA8888 textures: NO Cocos2d: cocos2d: GL supports NPOT textures: YES Cocos2d: cocos2d: GL supports discard_framebuffer: YES Cocos2d: cocos2d: compiled with NPOT support: NO Cocos2d: cocos2d: compiled with VBO support in TextureAtlas : NO Cocos2d: 列印str=:himi |
最後一句驗證了我們的儲存沒問題,那麼我們現在驗證是否真的存在xml中了,首先停止當前啟動並執行項目,然後刪除剛才代碼替換如下代碼:
1 |
CCLog( "列印str=:%s" ,CCUserDefault::sharedUserDefault()->getStringForKey( "key" ).c_str()); |
然後重新運行此項目,觀察控制台列印如下:
12345678910111213 |
Cocos2d: cocos2d: cocos2d-1.0.1-x-0.12.0 Cocos2d: cocos2d: GL_VENDOR: Imagination Technologies Cocos2d: cocos2d: GL_RENDERER: PowerVR SGX 543 Cocos2d: cocos2d: GL_VERSION: OpenGL ES-CM 1.1 IMGSGX543-63.14.2 Cocos2d: cocos2d: GL_MAX_TEXTURE_SIZE: 4096 Cocos2d: cocos2d: GL_MAX_MODELVIEW_STACK_DEPTH: 16 Cocos2d: cocos2d: GL supports PVRTC: YES Cocos2d: cocos2d: GL supports BGRA8888 textures: NO Cocos2d: cocos2d: GL supports NPOT textures: YES Cocos2d: cocos2d: GL supports discard_framebuffer: YES Cocos2d: cocos2d: compiled with NPOT support: NO Cocos2d: cocos2d: compiled with VBO support in TextureAtlas : NO Cocos2d: 列印str=:himi |
通過剛才的key->”key”,正常擷取到“himi”這個字串了,OK,監測沒問題;
那麼一般情況下我們會需要一個方法就是判定當前項目是否已經有儲存資料的xml檔案存在了,那麼Himi這裡說下,Cocos2dX預設源碼中有這個方法,但是並沒有提供給開發人員使用,因為此函數被private私人了,此函數源碼如所示:
那麼既然如此Himi這裡就自訂了一個檢測是否已存在資料xml的函數提供大家使用:(提醒:很多童鞋該說啦,為什麼不直接修改源碼將其public呢?!其實Himi也這麼想,但是如果你後期使用了新的Cocos2dX的版本,或者同事機器的Cocos2dX並沒有這麼修改源碼都會產生錯誤,反過來說,既然能很容易的寫出一個判斷的方法何必去動它呢,不是嗎?哈哈!)
1234567891011121314151617 |
.h檔案: bool isHaveSaveFile ( ) ; .cpp檔案: / / 當前項目是否存在儲存的xml檔案 bool HelloWorld : : isHaveSaveFile ( ) { if ( !CCUserDefault : : sharedUserDefault ( ) - > getBoolForKey ( "isHaveSaveFileXml" ) ) { CCUserDefault : : sharedUserDefault ( ) - > setBoolForKey ( "isHaveSaveFileXml" , true ) ; CCUserDefault : : sharedUserDefault ( ) - > flush ( ) ; / / 提交 / / CCLog ( "隱藏檔不存在,頭次開始載入遊戲" ) ; return false ; } else { / / CCLog ( "隱藏檔已存在" ) ; return true ; } } |
備忘:當儲存資料的xml不存在的時候,你的第一次儲存資料的時候預設會建立,路徑在你的app下的documents,如所示:
那麼這裡Himi強調一點!大家要注意setXX的函數的參數,例如以下這個函數:
setStringForKey (const char *pKey, const std::string &value)
第一個參數是const char*類型,不是string!!!!(Himi因為這個原因浪費不少時間,悲劇阿。)
Himi當時儲存寫了如下代碼,造成錯誤,如下:
1 |
CCUserDefault::sharedUserDefault()->setStringForKey( "" +823, sKey); |
錯誤如下:(儲存的key變成了路徑。。。。《資料是Himi加密後的》)
哎,鬱悶,這裡Himi犯錯希望童鞋們不要再範此錯誤,之前Himi一直想找 itoa 找個函數,但是怎麼都找不到!(c++ 應該存在的整形轉字串),但是Cocos2dX中沒有,並且最後Himi使用了與Cocos2dX引擎中的實現itoa的源碼,發現如下:
Cocos2dX內建的這個CCUserDefault並不是加密的,而是明文並且是.xml格式的,所以後續Himi準備寫一篇使用base64來進行加密的文章供大家參考;
本篇源碼下載: ”SaveDataForCocos2dx.zip” : http://vdisk.weibo.com/s/hq2Ys