【Cocos2d-x游戲開發】Cocos2d-x中的數據存儲技術


  一、引言

  數據存儲和網絡功能可以說是一款游戲中必不可少的功能,如果一款游戲不能保存進度那么它的可玩性必然大打折扣(試想一下,玩家辛辛苦苦玩了一整天的游戲,結果退出時告訴人家不能保存關卡信息,你明天還得從頭來再玩一遍。那玩家一定會掏出准備已久的西瓜刀~)

  其實Cocos2d-x引擎早已為我們開發者封裝好了多種數據存儲的類或者方法,包括簡單信息的存儲,文件的讀寫,SQLite數據庫和RAR格式的壓縮文件的讀取等等。(用心良苦啊!)其中大部分的存儲功能被封裝到了UserDefault類中。

  二、數據存儲

  1.UserDefault類

  UserDefault 是一個小型的數據管理類。你可以通過這個類保存並獲得基本類型值的數據。 例如:setBoolForKey("played", true) 將在數據庫中添加一個值為 true 的布爾型數據。 它的 key 是 "player"。可以通過 getBoolForKey("player") 獲取這個數據。

  UserDefault類提供了一些常用的方法用於讀取和存儲數據信息,如下表:

UserDefault類的常用方法
方法名 說              明
getBoolForKey 獲取bool類型的鍵值對的值
getIntegerForKey 獲取int類型的鍵值對的值
getFloatForKey 獲取float類型的鍵值對的值
getDoubleForKey 獲取double類型的鍵值對的值
getStringForKey 獲取String類型的鍵值對的值
getDataForKey 獲取二進制的鍵值對的值
setBoolForKey 存入bool類型的數據
setIntegerForKey 存入int類型的數據
setFloatForKey 存入float類型的數據
setDoubleForKey 存入double類型的數據
setStringForKey 存入String類型的數據
setDataForKey 存入二進制數據
flush 將內容保存到XML文件
getXMLFilePath 獲取XML文件的保存路徑
isXMLFileExist 判斷一個XML文件是否存在

  具體的參數及詳細的說明可以在Cocos2d-x的UserDefaultAPI文檔中查詢(吐槽一句Cocos2d-x的文檔真夠差勁的,相比之下Egret的文檔好很多。)

  OK,下面我們寫一個小例子,來看一下UserDefault這個類具體是怎么使用的,先上代碼:

 1 bool HelloWorld::init()
 2 {
 3     if ( !Layer::init() )
 4     {
 5         return false;
 6     }
 7     auto* background = LayerColor::create(Color4B(255, 255, 255, 255));
 8     addChild(background);
    //創建一個菜單按鈕
9 auto* readLabel = Label::create("read", "Arial", 56); 10 readLabel->setColor(Color3B(0, 0, 0)); 11 auto* pReadLabel = MenuItemLabel::create(readLabel, this, menu_selector(HelloWorld::readCallback)); 12 auto* buttonReadLabel = Menu::create(pReadLabel, NULL); 13 buttonReadLabel->setPosition(320, 260); 14 addChild(buttonReadLabel); 15 auto* saveLabel = Label::create("save", "Arial", 56); 16 saveLabel->setColor(Color3B(0, 0, 0)); 17 auto* pSaveLabel = MenuItemLabel::create(saveLabel, this, menu_selector(HelloWorld::saveCallback)); 18 auto* buttonSaveLabel = Menu::create(pSaveLabel, NULL); 19 buttonSaveLabel->setPosition(320, 100); 20 addChild(buttonSaveLabel); 21 UserDefault::sharedUserDefault()->setBoolForKey("isExisted",false); 22 return true; 23 } 24 void HelloWorld::readCallback(Ref* pSender) 25 { 26 CCLOG("============================================================"); 27 CCLOG("reading begin!");
    //根據isExisted的值來判斷,是否數據被寫入
28 if (UserDefault::sharedUserDefault()->getBoolForKey("isExisted")) 29 {
      //讀取鍵值為Int的內容並輸出
30 int intVar = UserDefault::sharedUserDefault()->getIntegerForKey("int"); 31 CCLOG("the int is:%d", intVar);
      //讀取鍵值為float的內容並輸出      
32 float floatVar = UserDefault::sharedUserDefault()->getFloatForKey("float"); 33 CCLOG("the float is:%f", floatVar);
      //讀取鍵值為string的內容並輸出
34 std::string str = UserDefault::sharedUserDefault()->getStringForKey("string"); 35 CCLOG("the string is:%s", str); 36 }
    //如果isExisted的鍵值為false的話,說明信息沒有被保存,不可用
37 else 38 { 39 CCLOG("not exist!"); 40 } 41 CCLOG("============================================================"); 42 } 43 void HelloWorld::saveCallback(Ref* pSender) 44 { 45 CCLOG("============================================================"); 46 CCLOG("save begin!"); 47 UserDefault::sharedUserDefault()->setIntegerForKey("int", 999); 48 UserDefault::sharedUserDefault()->setFloatForKey("float", 3.1415926); 49 UserDefault::sharedUserDefault()->setStringForKey("string", "this is a string!"); 50 UserDefault::sharedUserDefault()->setBoolForKey("isExisted", true); 51 CCLOG("saved file path is %s", UserDefault::sharedUserDefault()->getXMLFilePath()); 52 CCLOG("============================================================"); 53 }

  程序運行起來以后可以看到read和save兩個按鈕,點擊他們可以看到在控制台打印出來的信息,如下圖:

  

  可以看到,數據信息已經被成功的寫入並且讀取出來了,而且還打印了文件的存放路徑。這種方式特別適合保存游戲進度和最高分、排行榜等內容比較少的數據。但是如果數據量比較大的時候就需要采取別的方式了,比如文件讀寫的方式。

  二、Cocos2dx中的文件讀寫

 1 bool HelloWorld::init()
 2 {
 3     if ( !Layer::init() )
 4     {
 5         return false;
 6     }
 7     // 創建一個菜單按鈕,用於讀取文件中的內容
 8     auto* background = LayerColor::create(Color4B(255, 255, 255, 255));
 9     addChild(background);
10     auto* readLabel = Label::create("read", "Arial", 56);
11     readLabel->setColor(Color3B(0, 0, 0));
12     auto* pReadLabel = MenuItemLabel::create(readLabel, this, menu_selector(HelloWorld::readCallback));
13     auto* buttonReadLabel = Menu::create(pReadLabel, NULL);
14     buttonReadLabel->setPosition(320, 260);
15     addChild(buttonReadLabel);
16     auto* saveLabel = Label::create("save", "Arial", 56);
17     saveLabel->setColor(Color3B(0, 0, 0));
18     auto* pSaveLabel = MenuItemLabel::create(saveLabel, this, menu_selector(HelloWorld::saveCallback));
19     auto* buttonSaveLabel = Menu::create(pSaveLabel, NULL);
20     buttonSaveLabel->setPosition(320, 100);
21     addChild(buttonSaveLabel);
22     return true;
23 }
24 void HelloWorld::readCallback(Ref* pSender)
25 {
26     CCLOG("============================================================");
27     std::string path = FileUtils::sharedFileUtils()->getWritablePath()+"test.txt";
28     // 輸出文件路徑
29     CCLOG("path = %s", path.c_str());
30     // 創建一個文件指針
31     FILE* file = fopen(path.c_str(), "r");
32     if (file) {
33         char* buf;  //要獲取的字符串  
34         int len;    //獲取的長度  
35         // 獲取文件長度長度
36         fseek(file, 0, SEEK_END);   //移到尾部  
37         len = ftell(file);          //提取長度  
38         rewind(file);               //回歸原位  
39         CCLOG("count the file content len = %d", len);
40         //分配buf空間  
41         buf = (char*)malloc(sizeof(char) * len + 1);
42         if (!buf) 
43         {
44             CCLOG("malloc space is not enough.");
45         } 
46         //讀取進的buf,單位大小,長度,文件指針  
47         int rLen = fread(buf, sizeof(char), len, file);
48         buf[rLen] = '\0';
49         CCLOG("has read Length = %d", rLen);
50         CCLOG("has read content = %s", buf);
51         fclose(file);
52         free(buf);
53     }
54     else
55     {
56         CCLOG("open file error.");
57     }
58     CCLOG("============================================================");
59 }
60 void HelloWorld::saveCallback(Ref* pSender)
61 {
62     CCLOG("============================================================");
63     std::string path = CCFileUtils::sharedFileUtils()->getWritablePath() + "test.txt";
64     FILE* file = fopen(path.c_str(), "w");
65     if (file) 
66     {
67         char* pContent = "this is a word";
68         fputs(pContent, file);
69         CCLOG("save file succeed.");
70         fclose(file);
71     }
72     else
73     {
74         CCLOG("save file error.");
75     }
76     CCLOG("============================================================");
77 }

 程序運行調試圖:

 

  Cocos2d-x中文件讀寫的方式和C++對文件的操作是一樣的,先創建一個文件指針指向一個文件,然后打開這個文件,接着寫入數據,最后關閉文件。以下是詳細說明:

  File對象:文件對象,用於創建文件,操作文件。

  fopen:打開一個文件,可以根據參數的不同來決定文件的打開方式(比如 r,w,a等等)。

  fseek:移動文件指針,可以將指針指向文件中特定位置的字符。

  ftell:獲取文件指針相對於文件開頭的距離。

  malloc:為指針分配內存。

  fread:讀取一個文件,需要輸入緩沖區的地址,單位大小,長度和文件指針。

  更多詳細的文件操作內容可以移步此篇博文

  其實在Cocos2d-x中還有利用比如csv,json等保存數據的方法,但由於篇幅限制,本篇博客中我們就不再探討了,以后的博客中會詳細的介紹json和csv的操作。

 

  本篇博客所有代碼已經同步到Github:

  UserDefault類使用:https://github.com/XINCGer/Cocos2d-X_Tools/tree/master/Cocos2d-x_Demo/LocalDataSave

  文件讀寫操作:https://github.com/XINCGer/Cocos2d-X_Tools/tree/master/Cocos2d-x_Demo/FileSystemInCocos2dx

  下一篇博客,我們將學習Cocos2d-X中的弱聯網技術。

 

作者:馬三小伙兒
出處:http://www.cnblogs.com/msxh/p/5744177.html 
請尊重別人的勞動成果,讓分享成為一種美德,歡迎轉載。另外,文章在表述和代碼方面如有不妥之處,歡迎批評指正。留下你的腳印,歡迎評論!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM