专栏首页游戏开发那些事【Cocos2d-x游戏开发】Cocos2d-x中的数据存储技术

【Cocos2d-x游戏开发】Cocos2d-x中的数据存储技术

一、引言

  数据存储和网络功能可以说是一款游戏中必不可少的功能,如果一款游戏不能保存进度那么它的可玩性必然大打折扣(试想一下,玩家辛辛苦苦玩了一整天的游戏,结果退出时告诉人家不能保存关卡信息,你明天还得从头来再玩一遍。那玩家一定会掏出准备已久的西瓜刀~)

  其实Cocos2d-x引擎早已为我们开发者封装好了多种数据存储的类或者方法,包括简单信息的存储,文件的读写,SQLite数据库和RAR格式的压缩文件的读取等等。(用心良苦啊!)其中大部分的存储功能被封装到了UserDefault类中。

二、数据存储

1.UserDefault类

UserDefault 是一个小型的数据管理类。你可以通过这个类保存并获得基本类型值的数据。 例如:setBoolForKey("played", true) 将在数据库中添加一个值为 true 的布尔型数据。 它的 key 是 "player"。可以通过 getBoolForKey("player") 获取这个数据。

  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 请尊重别人的劳动成果,让分享成为一种美德,欢迎转载。另外,文章在表述和代码方面如有不妥之处,欢迎批评指正。留下你的脚印,欢迎评论!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【Unity游戏开发】你真的了解UGUI中的IPointerClickHandler吗?

      马三在最近的开发工作中遇到了一个比较有意思的bug:“TableViewCell上面的某些自定义UI组件不能响应点击事件,并且它的父容器TableView也...

    马三小伙儿
  • 【Cocos2d-x游戏开发】解决Cocos2d-x中文乱码的三种方法

      众所周知,Cocos2d-x是一款不错的开源引擎,但是在Cocos2d-x中直接使用中文是无法正确显示的。比如下面的情况: 

    马三小伙儿
  • 【python游戏编程之旅】第四篇---pygame中加载位图与常用的数学函数。

    本系列博客介绍以python+pygame库进行小游戏的开发。有写的不对之处还望各位海涵。

    马三小伙儿
  • 《哔哩哔哩助手》助你快速成为B站老司机

    B站全名哔哩哔哩,域名bilibili.com ,名字源于《魔法禁书目录》中 御坂美琴 的昵称,所以B站动漫出现 bilibili译制的字样时, 会有很多弹幕刷...

    zhaoolee
  • 002.DHCP配置

    注意:为了配置清晰,可将多余的subnet删除,仅仅保留需要配置的,若无需为特定主机配置dhcp,也可将host相关项删除。

    木二
  • JMeter专题系列(四)参数化

    参数化:录制脚本中有登录操作,需要输入用户名和密码,假如系统不允许相同的用户名和密码同时登录,或者想更好的模拟多个用户来登录系统。

    流柯
  • 如何有效保护源代码 —— .m脚本文件?

    在实际情况中可能会遇到这样的事情,我们在分享自己编写的matlab程序时只是为了演示程序所实现的功能,并不希望对方看见源代码。要怎样才能实现既能加密源代码又能够...

    艾木樨
  • 如何上线付费阅读,哪些内容能在微信卖钱?

    昨天朋友圈有人说,微信公众平台即将上线『付费阅读』功能,运营者可以选择某一篇图文消息为强制付费才能阅读,并且可设置金额和引导语。如果这个消息为真,微信对于内容商...

    罗超频道
  • 人工智能是怎么发现系外行星的?看来想发现外星人也要靠AI

    如何运用机器学习,发现新的系外行星? 几千年来,人们仰望星星,记录、观察天文现象,并从中发现其运行模式。第一批天文学家所认定的天体是行星,由于行星在夜空中看似不...

    企鹅号小编
  • #必读#微信付费阅读功能上线在即,哪些内容可以到微信卖钱?

    昨晚多家媒体报道微信付费阅读功能即将推出。事情原委是马化腾在知名科技评论人keso(洪波)朋友圈的留言表示“微信公众号付费订阅”即将上线。 ? 事实上,早在一年...

    罗超频道

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动