一、引言

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

  其实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. [Head First设计模式]生活中学设计模式——外观模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

  2. visio二次开发——图纸解析

    (转发请注明来源:http://www.cnblogs.com/EminemJK/) visio二次开发的案例或者教程,国内真的非常少,这个项目也是花了不少时间来研究visio的相关知识,困难之所以难 ...

  3. 【Go入门教程3】流程(if、goto、for、switch)和函数(多个返回值、变参、传值与传指针、defer、函数作为值/类型、Panic和Recover、main函数和init函数、import)

    这小节我们要介绍Go里面的流程控制以及函数操作. 流程控制 流程控制在编程语言中是最伟大的发明了,因为有了它,你可以通过很简单的流程描述来表达很复杂的逻辑.Go中流程控制分三大类:条件判断,循环控制和 ...

  4. 【安卓】aidl.exe E 10744 10584 io_delegate.cpp:102] Error while creating directories: Invalid argument

    这几天在使用.aidl文件的时候eclipse的控制台总是爆出如下提示: aidl.exe E 10744 10584 io_delegate.cpp:102] Error while creatin ...

  5. http协议相关-待续

    // 关于http的东西 function httpAction() { // http://localhost/blog/testurl.php?id=5 到目前为止 // 获取当前域名 // 获取 ...

  6. Hadoop家族的各个成员

    官方定义:hadoop是一个开发和运行处理大规模数据的软件平台.核心词语是平台,也就是说我们有大量的数据,又有好几个电脑,我们知道应该把处理数据的任务分解到各个电脑上,但是不知道怎样分配任务,怎样回收 ...

  7. rcnn学习(六):imdb.py学习

    # -------------------------------------------------------- # Fast R-CNN # Copyright (c) 2015 Microso ...

  8. BZOJ 4725: [POI2017]Reprezentacje ró?nicowe

    Description 一个数列. \(a_1=1,a_2=2\) 当 \(n>2\) 时 \[a_n = \{  \begin {matrix} 2a_{n-1},\text{n is an ...

  9. DES & 3DES 加密算法

    JAVA坑 跟其他公司java的对接口,一个细节对到吐血,具体: DesUtil.java(别人的反例) //package base_class; import java.io.IOExceptio ...

  10. jquery 赋值文本框输入框

    jQuery("#mrId option[value='" + extValue + "']").attr("selected", true ...