一、引言

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

  其实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这个类具体是怎么使用的,先上代码:

 bool HelloWorld::init()
{
if ( !Layer::init() )
{
return false;
}
auto* background = LayerColor::create(Color4B(, , , ));
addChild(background);
    //创建一个菜单按钮
auto* readLabel = Label::create("read", "Arial", );
readLabel->setColor(Color3B(, , ));
auto* pReadLabel = MenuItemLabel::create(readLabel, this, menu_selector(HelloWorld::readCallback));
auto* buttonReadLabel = Menu::create(pReadLabel, NULL);
buttonReadLabel->setPosition(, );
addChild(buttonReadLabel);
auto* saveLabel = Label::create("save", "Arial", );
saveLabel->setColor(Color3B(, , ));
auto* pSaveLabel = MenuItemLabel::create(saveLabel, this, menu_selector(HelloWorld::saveCallback));
auto* buttonSaveLabel = Menu::create(pSaveLabel, NULL);
buttonSaveLabel->setPosition(, );
addChild(buttonSaveLabel);
UserDefault::sharedUserDefault()->setBoolForKey("isExisted",false);
return true;
}
void HelloWorld::readCallback(Ref* pSender)
{
CCLOG("============================================================");
CCLOG("reading begin!");
    //根据isExisted的值来判断,是否数据被写入
if (UserDefault::sharedUserDefault()->getBoolForKey("isExisted"))
{
      //读取键值为Int的内容并输出
int intVar = UserDefault::sharedUserDefault()->getIntegerForKey("int");
CCLOG("the int is:%d", intVar);
      //读取键值为float的内容并输出      
float floatVar = UserDefault::sharedUserDefault()->getFloatForKey("float");
CCLOG("the float is:%f", floatVar);
      //读取键值为string的内容并输出
std::string str = UserDefault::sharedUserDefault()->getStringForKey("string");
CCLOG("the string is:%s", str);
}
    //如果isExisted的键值为false的话,说明信息没有被保存,不可用
else
{
CCLOG("not exist!");
}
CCLOG("============================================================");
}
void HelloWorld::saveCallback(Ref* pSender)
{
CCLOG("============================================================");
CCLOG("save begin!");
UserDefault::sharedUserDefault()->setIntegerForKey("int", );
UserDefault::sharedUserDefault()->setFloatForKey("float", 3.1415926);
UserDefault::sharedUserDefault()->setStringForKey("string", "this is a string!");
UserDefault::sharedUserDefault()->setBoolForKey("isExisted", true);
CCLOG("saved file path is %s", UserDefault::sharedUserDefault()->getXMLFilePath());
CCLOG("============================================================");
}

  程序运行起来以后可以看到read和save两个按钮,点击他们可以看到在控制台打印出来的信息,如下图:

  

  可以看到,数据信息已经被成功的写入并且读取出来了,而且还打印了文件的存放路径。这种方式特别适合保存游戏进度和最高分、排行榜等内容比较少的数据。但是如果数据量比较大的时候就需要采取别的方式了,比如文件读写的方式。

  二、Cocos2dx中的文件读写

 bool HelloWorld::init()
{
if ( !Layer::init() )
{
return false;
}
// 创建一个菜单按钮,用于读取文件中的内容
auto* background = LayerColor::create(Color4B(, , , ));
addChild(background);
auto* readLabel = Label::create("read", "Arial", );
readLabel->setColor(Color3B(, , ));
auto* pReadLabel = MenuItemLabel::create(readLabel, this, menu_selector(HelloWorld::readCallback));
auto* buttonReadLabel = Menu::create(pReadLabel, NULL);
buttonReadLabel->setPosition(, );
addChild(buttonReadLabel);
auto* saveLabel = Label::create("save", "Arial", );
saveLabel->setColor(Color3B(, , ));
auto* pSaveLabel = MenuItemLabel::create(saveLabel, this, menu_selector(HelloWorld::saveCallback));
auto* buttonSaveLabel = Menu::create(pSaveLabel, NULL);
buttonSaveLabel->setPosition(, );
addChild(buttonSaveLabel);
return true;
}
void HelloWorld::readCallback(Ref* pSender)
{
CCLOG("============================================================");
std::string path = FileUtils::sharedFileUtils()->getWritablePath()+"test.txt";
// 输出文件路径
CCLOG("path = %s", path.c_str());
// 创建一个文件指针
FILE* file = fopen(path.c_str(), "r");
if (file) {
char* buf; //要获取的字符串
int len; //获取的长度
// 获取文件长度长度
fseek(file, , SEEK_END); //移到尾部
len = ftell(file); //提取长度
rewind(file); //回归原位
CCLOG("count the file content len = %d", len);
//分配buf空间
buf = (char*)malloc(sizeof(char) * len + );
if (!buf)
{
CCLOG("malloc space is not enough.");
}
//读取进的buf,单位大小,长度,文件指针
int rLen = fread(buf, sizeof(char), len, file);
buf[rLen] = '\0';
CCLOG("has read Length = %d", rLen);
CCLOG("has read content = %s", buf);
fclose(file);
free(buf);
}
else
{
CCLOG("open file error.");
}
CCLOG("============================================================");
}
void HelloWorld::saveCallback(Ref* pSender)
{
CCLOG("============================================================");
std::string path = CCFileUtils::sharedFileUtils()->getWritablePath() + "test.txt";
FILE* file = fopen(path.c_str(), "w");
if (file)
{
char* pContent = "this is a word";
fputs(pContent, file);
CCLOG("save file succeed.");
fclose(file);
}
else
{
CCLOG("save file error.");
}
CCLOG("============================================================");
}

 程序运行调试图:

 

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

【Cocos2d-x游戏开发】Cocos2d-x中的数据存储技术的更多相关文章

  1. 【转】 [Unity3D]手机3D游戏开发:场景切换与数据存储(PlayerPrefs 类的介绍与使用)

    http://blog.csdn.net/pleasecallmewhy/article/details/8543181 在Unity中的数据存储和iOS中字典的存储基本相同,是通过关键字实现数据存储 ...

  2. 【Cocos2d-x游戏开发】Cocos2d-x中的弱联网技术

    在上一篇博客中,我们一起学习了如何在Cocos2d-x中存储数据和读取信息,本篇博客我们将一起讨论和数据存储同样重要的联网技术. 一.弱联网技术介绍 在网络游戏中许多重要的功能都需要网络连接,而根据需 ...

  3. iOS cocos2d 2游戏开发实战(第3版)书评

    2013是游戏爆发的一年,手游用户也是飞速暴增.虽然自己不做游戏,但也是时刻了解手机应用开发的新动向.看到CSDN的"写书评得技术图书赢下载分"活动,就申请了一本<iOS c ...

  4. iOS开发UI篇—ios应用数据存储方式(XML属性列表-plist)

    iOS开发UI篇—ios应用数据存储方式(XML属性列表-plist) 一.ios应用常用的数据存储方式 1.plist(XML属性列表归档) 2.偏好设置 3.NSKeydeArchiver归档(存 ...

  5. 67.Android中的数据存储总结

    转载:http://mp.weixin.qq.com/s?__biz=MzIzMjE1Njg4Mw==&mid=2650117688&idx=1&sn=d6c73f9f04d0 ...

  6. iOS开发UI篇—ios应用数据存储方式(偏好设置)

    iOS开发UI篇—ios应用数据存储方式(偏好设置) 一.简单介绍 很多iOS应用都支持偏好设置,比如保存用户名.密码.字体大小等设置,iOS提供了一套标准的解决方案来为应用加入偏好设置功能 每个应用 ...

  7. iOS开发UI篇—ios应用数据存储方式(归档)

    iOS开发UI篇—ios应用数据存储方式(归档)  一.简单说明 在使用plist进行数据存储和读取,只适用于系统自带的一些常用类型才能用,且必须先获取路径相对麻烦: 偏好设置(将所有的东西都保存在同 ...

  8. iOS开发UI篇—ios应用数据存储方式(归档) :转发

    本文转发至:文顶顶http://www.cnblogs.com/wendingding/p/3775293.html iOS开发UI篇—ios应用数据存储方式(归档)  一.简单说明 在使用plist ...

  9. 20.1翻译系列:EF 6中自动数据迁移技术【EF 6 Code-First系列】

    原文链接:https://www.entityframeworktutorial.net/code-first/automated-migration-in-code-first.aspx EF 6 ...

随机推荐

  1. wamp(win1064位家庭版+apache2.4.20+php5.5.37+mysql5.5.50)环境搭建

    wamp环境搭建之软件准备 *php:http://windows.php.net/downloads/releases/php-5.5.37-Win32-VC11-x86.zip *apache:h ...

  2. 20145204&20145212信息安全系统实验三报告

    实时系统的移植 实验目的与要求 1.根据实验指导书进行实时软件的安装 2.配置实验环境,并对软件进行测试. 3.正确使用连接线等仪器,注意保护试验箱. 实验内容与步骤 1.连接 arm 开发板 连接实 ...

  3. 理清Java中的编码解码转换

    1.字符集及编码方式 概括:字符编码方式及大端小端 详细:彻底理解字符编码 可以通过Charset.availableCharsets()获取Java支持的字符集,以JDK8为例,得到其支持的字符集: ...

  4. Javascript 俄罗斯方块 游戏代码解释!

    俄罗斯方块代码说明 /** 名称:Javascript 俄罗斯方块! 作者:Gloot 邮箱:glootz@gmail.com QQ:345268267 网站:http://www.cnblogs.c ...

  5. codevs1228 苹果树

    题目描述 Description 在卡卡的房子外面,有一棵苹果树.每年的春天,树上总会结出很多的苹果.卡卡非常喜欢吃苹果,所以他一直都精心的呵护这棵苹果树.我们知道树是有很多分叉点的,苹果会长在枝条的 ...

  6. [Algorithm] 字符串匹配算法——KMP算法

    1 字符串匹配 字符串匹配是计算机的基本任务之一. 字符串匹配是什么?举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串& ...

  7. SSAS动态添加分区(一)

    一.动态分区的好处就不说了,随着时间的推移,不可能一个度量值组都放在一个分区中,处理速度非常慢,如何动态添加分区,如何动态处理分区,成为了很多新手BI工程师一个头痛的问题,废话不多说,分享一下我的经验 ...

  8. Java实现Excel的操作

    JAVA EXCEL API: 开源项目,通过它Java开发人员可以读取Excel文件的内容.创建新的Excel文件.更新已经存在的Excel文件.使用该API非Windows操作系统也可以通过纯Ja ...

  9. PHP获取指定月份的第一天开始和最后一天结束的时间戳函数

    <?php /** * 获取指定月份的第一天开始和最后一天结束的时间戳 * * @param int $y 年份 $m 月份 * @return array(本月开始时间,本月结束时间) */ ...

  10. CentOS6.3编译安装Memcached

    要用到如下源码包: /usr/local/src/memcached/libevent-2.0.21-stable.tar.gz /usr/local/src/memcached/memcached- ...