cocos2dx - Sqlite简单封装使用
前言:
一般游戏需要在手机上记录一些简单的信息,用来保存游戏的进度,玩家的分数等。SQLite作为轻量级、跨平台的关系型数据库,相当适合用于游戏数据的存储。
由于没有加密,有安全性问题,数据上还需要自己做些加密验证等。
封装效果
为了达到简单易用的效果,封装后接口大致如下。通过仅通过调用GetData和SetData来获取数据及存储数据。
class CDataMgr
{
public:
static CDataMgr* getInstance(); static void destroyInstance(); const SSqlData& GetData(enDataType nType){ return m_mKeyValue[nType]; } void SetData(enDataType nType, SSqlData& data);
private:
void GetSqlData(enSqlTableType nSqlType, std::vector<enDataType>& vDataType); void SaveSqlTable(enSqlTableType nSqlType); void OpenSql(enSqlTableType nType); // 打开数据库操作 void CloseSql(); // 关闭数据库操作 CDataMgr();
~CDataMgr(); std::map<enDataType, SSqlData> m_mKeyValue; // 程序当前的值
sqlite3 * m_pSqlData; // 数据库指针 };
辅助数据结构
Get及Set得到的数据需要知道类型且可以得到正常的值,同时还需要设置在sqlite中字段名字等,因此需要几个辅助的结构体来存储数据类型等。如下:
// 数据枚举
enum class enDataType
{
SOUND, // 声音数据 0x01 音乐 0x02 音效 (1:开启,0:关闭)
PLAYERID, // 上次GAMECENTER玩家数据
ISGUIDED, // 是否已经引导过
LASTTIME, // 上次时间 PLAYER_INDEX, // 每个的索引
MONEY, // 金币
RECORD, // 记录
}; // Sqlite表格类型
enum class enSqlTableType
{
DEFAULT, // 默认数据存储 声音等
PLAYER, // 玩家数据存储 金币
}; // 存储数据类型
enum class enSqlDataType
{
NONE, // 没有数据
INT, // int类型
LONG, // long类型
BOOL, // bool 类型
STRING, // string 类型
}; // 数据结构体
struct SSqlData
{
public:
SSqlData()
{
memset(&udata, , sizeof(udata));
}
SSqlData(enSqlTableType ntable, enSqlDataType ntype, std::string name)
:nSqlTableType(ntable), nSqlDataType(ntype), sSqlDataName(name)
{
memset(&udata, , sizeof(udata));
} // 实际数据
union UData
{
int _intData;
long _longData;
bool _boolData;
};
UData udata;
std::string _strData; enSqlTableType nSqlTableType; // 数据表格
enSqlDataType nSqlDataType; // 数据库中数据类型
std::string sSqlDataName; // 数据库中名字
};
简单说明:
1、SSqlData是实际设置获取的数据,里面包含有Sqlite的字段名字,数据类型及实际保存数据等。
2、enSqlDataType 是数据存储类型的枚举。
3、enSqlTableType 是数据表格的枚举类型,一般游戏至少有2张表格,分别用来存储每个玩家数据(分数)及所有玩家共同的数据(声音)。
4、enDataType 是列举了所有的游戏存储值的枚举,用来索引SSqlData的,游戏通过enDataType 来获取SSqlData。
数据初始化描述
游戏初始化时在DataMgr的构造函数中需要对所有的枚举值进行描述,设置所属表格及字段类型,字段名等。同时还需要从Sqlite取出默认的数据,如下:
CDataMgr::CDataMgr() :m_pSqlData()
{
// 初始化key-value
m_mKeyValue[enDataType::SOUND] = SSqlData(enSqlTableType::DEFAULT, enSqlDataType::INT, "sound");
m_mKeyValue[enDataType::PLAYERID] = SSqlData(enSqlTableType::DEFAULT, enSqlDataType::STRING, "playerId");
m_mKeyValue[enDataType::ISGUIDED] = SSqlData(enSqlTableType::DEFAULT, enSqlDataType::BOOL, "isGuided");
m_mKeyValue[enDataType::LASTTIME] = SSqlData(enSqlTableType::DEFAULT, enSqlDataType::LONG, "lastTime"); m_mKeyValue[enDataType::MONEY] = SSqlData(enSqlTableType::PLAYER, enSqlDataType::LONG, "money");
m_mKeyValue[enDataType::RECORD] = SSqlData(enSqlTableType::PLAYER, enSqlDataType::LONG, "record");
m_mKeyValue[enDataType::PLAYER_INDEX] = SSqlData(enSqlTableType::PLAYER, enSqlDataType::STRING, "playerId"); std::vector<enDataType> vDataType;
vDataType.push_back(enDataType::PLAYERID);
vDataType.push_back(enDataType::SOUND);
vDataType.push_back(enDataType::LASTTIME);
vDataType.push_back(enDataType::ISGUIDED);
GetSqlData(enSqlTableType::DEFAULT, vDataType); // 获取数据库记录 vDataType.clear();
vDataType.push_back(enDataType::MONEY);
vDataType.push_back(enDataType::RECORD);
GetSqlData(enSqlTableType::PLAYER, vDataType); // 获取数据库记录
}
数据存储
为了节省效率,在实际SetData及GetData并不会从Sqlite中存取,而是从缓存的 m_mKeyValue 中取值设置。然而当玩家角色发生变化及游戏结束就必须及时对玩家数据进行存储。
因此在析构函数及SetData中有如下操作:
CDataMgr::~CDataMgr()
{
SaveSqlTable(enSqlTableType::DEFAULT);
SaveSqlTable(enSqlTableType::PLAYER);
} void CDataMgr::SetData(enDataType nType, SSqlData& data)
{
// 玩家角色变化更新玩家数据
if (enDataType::PLAYERID == nType)
{
SaveSqlTable(enSqlTableType::PLAYER);
m_mKeyValue[nType] = data;
std::vector<enDataType> vDataType;
vDataType.push_back(enDataType::MONEY);
vDataType.push_back(enDataType::RECORD);
GetSqlData(enSqlTableType::PLAYER, vDataType);
}
else
{
m_mKeyValue[nType] = data;
}
}
测试数据:
SSqlData guid_data = CDataMgr::getInstance()->GetData(enDataType::ISGUIDED);
SSqlData last_data = CDataMgr::getInstance()->GetData(enDataType::LASTTIME);
SSqlData player_data = CDataMgr::getInstance()->GetData(enDataType::PLAYERID);
SSqlData record_data = CDataMgr::getInstance()->GetData(enDataType::RECORD); CCLOG("guid_data:%d", guid_data.udata._boolData ? : );
CCLOG("lasttime:%ld", last_data.udata._longData);
CCLOG("player:%s", player_data._strData.c_str());
CCLOG("record:%ld", record_data.udata._longData); guid_data.udata._boolData = true;
player_data._strData = "xxxxxxxxxxzzzzzzzzzz___1";
record_data.udata._longData = ; CDataMgr::getInstance()->SetData(enDataType::ISGUIDED, guid_data); // 通用引导数据变化
CDataMgr::getInstance()->SetData(enDataType::PLAYERID, player_data); // 登录玩家变化
CDataMgr::getInstance()->SetData(enDataType::RECORD, record_data); // 玩家记录变化 record_data = CDataMgr::getInstance()->GetData(enDataType::RECORD);
CCLOG("record__1 :%ld", record_data.udata._longData); player_data._strData = "xxxxxxxxxxzzzzzzzzzz_____2";
CDataMgr::getInstance()->SetData(enDataType::PLAYERID, player_data); // 登录玩家变化
record_data = CDataMgr::getInstance()->GetData(enDataType::RECORD);
CCLOG("record__2 :%ld", record_data.udata._longData);
结果如下图:

当然,也可以通过sqliteadmin之类的软件直接打开db文件查看数据,因为没加密~~~~~~~~~~
完整代码地址:https://github.com/mydishes/cocos2dx-Ex/tree/master/SqliteMgr
cocos2dx - Sqlite简单封装使用的更多相关文章
- iOS sqlite 增删改查 简单封装(基于 FMDB)
/** * 对 sqlite 的使用进行简单封装,仅涉及简单的单表 增删改查 * * 基于 FMDB * * 操作基于 model ,数据库表字段与 model 属性一一对应,对 model 整 ...
- FMDB简单封装和使用
工具:火狐浏览器+SQLite Manager插件 ; Xcode; FMDB库; 效果: 项目地址: https://github.com/sven713/PackFMDB 主要参考这两篇博客: 1 ...
- iOS开发数据库篇—SQLite简单介绍
iOS开发数据库篇—SQLite简单介绍 一.离线缓存 在项目开发中,通常都需要对数据进行离线缓存的处理,如新闻数据的离线缓存等. 说明:离线缓存一般都是把数据保存到项目的沙盒中.有以下几种方式 (1 ...
- 【转】 iOS开发数据库篇—SQLite简单介绍
开始学SQLite啦, 原文: http://www.cnblogs.com/wendingding/p/3868893.html iOS开发数据库篇—SQLite简单介绍 一.离线缓存 在项目开发中 ...
- SQLite简单介绍
一.离线缓存 在项目开发中,通常都需要对数据进行离线缓存的处理,如新闻数据的离线缓存等. 说明:离线缓存一般都是把数据保存到项目的沙盒中.有以下几种方式 (1)归档:NSCodeing.NSKeyed ...
- .net core 中简单封装Dapper.Extensions 并使用sqlsuger自动生成实体类
引言 由公司需要使用dapper 同时支持多数据库 又需要支持实体类 又需要支持sql 还需要支持事务 所以采用了 dapper + dapperExtensions 并配套 生成实体类小工具的方 ...
- Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池
前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...
- Android--Retrofit+RxJava的简单封装(三)
1,继续接着上一篇的讲讲,话说如果像上一篇这样的话,那么我们每一次请求一个结构都要创建一堆的Retrofit对象,而且代码都是相同的,我们可以试试封装一下 先创建一个HttpMethods类,将Ret ...
- okhttp3 get post 简单封装
最近打算在新项目中使用 okhttp3, 简单封装了一下异步 get post 因为 CallBack 也是在子线程中执行,所以用到了 Handler public class MyOkHttpCli ...
随机推荐
- web切图的几个快捷键及总结
自由的控制视图系列 自由的浏览图片:按住空格后,鼠标拖动 自由的缩放图片:按住alt+滚轮 切换到实际像素(100%):Ctrl + 1 工作区类型切换:Tab 控制内容系列 通过画面上点选一个图 ...
- 8个超震撼的HTML5和纯CSS3动画源码
HTML5和CSS3之所以强大,不仅因为现在大量的浏览器的支持,更是因为它们已经越来越能满足现代开发的需要.Flash在几年之后肯定会消亡,那么HTML5和CSS3将会替代Flash.今天我们要给大家 ...
- 关于Linux中cd的一些快捷用法
cd 命令使用的一些小技巧 cd 进入主目录 cd ~ 同样进入主目录 cd - 返回当前目录之前所在的目录 cd .. 返回上级目录 cd ../.. 返回上级的上级目录 cd !$ 把上个命令的参 ...
- 201521123033《Java程序设计》第7周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 参考资料: XMind answer: 2. 书面作业 1.ArrayList代码分析 1.1 解释ArrayList的co ...
- 201521123078 《Java程序设计》第9周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 1.题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前编写的代码中经常出现什么异常. ...
- 201521123085 《Java程序设计》第14周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自 ...
- eclipse: eclipse导入工程出现大红叹号
总结: 问题原因:工程中classpath中指向的包路径错误 解决办法:到BUILDPATH CONFIG````中,liberaies中 出现红色叉号的包为路径错误的包.到classpath中修改相 ...
- 市场主流5款HTML5开发框架详解
我们经常听见的前端框架是一个非常大的范词,因为前端框架都是基于JS.CSS.HTML5技术开发实现的,不过选择一个HTML5开发框架需要考虑哪些方面,首先就是需要什么样的功能,其次就是技术实现,不过当 ...
- 私人订制——属于你自己的Linux
一.前言 Linux操作系统至1991年10月5日诞生以来,就其开源性和自由性得到了很多技术大牛的青睐,每个Linux爱好者都为其贡献了自己的一份力,不管是在Linux内核还是开源软件等方面,都为我们 ...
- C#关于通过反射PropertyType判读字符串类型方法
今天在通过反射判读实体属性来映射数据库表是否修改的时候发现,最开始我通过 p.GetValue(entity) == null && p.PropertyType.IsValueTyp ...