一、引言
数据存储和网络功能可以说是一款游戏中必不可少的功能,如果一款游戏不能保存进度那么它的可玩性必然大打折扣(试想一下,玩家辛辛苦苦玩了一整天的游戏,结果退出时告诉人家不能保存关卡信息,你明天还得从头来再玩一遍。那玩家一定会掏出准备已久的西瓜刀~)
其实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这个类具体是怎么使用的,先上代码:
代码语言:javascript复制 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中的文件读写
代码语言:javascript复制 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] = '