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 ...
随机推荐
- 团队作业4--第一次项目冲刺(Alpha版本) 4
一.Daily Scrum Meeting照片 二.燃尽图 三.项目进展 完成对查重结果的写出与保存,将查重结果写出并导出保存为Excel形式 四.困难与问题 对查重结果的保存,当有多份文档进行比较的 ...
- 201521123042《Java程序设计》 第7周学习总结
1. 本周学习总结 网上看了很多资料,发现这一张图总结的还不错就引用过来了.但是最上面的Map和Collection之间的关系应该是依赖,不是Produces. ①概述:Java集合框架主要包括两种类 ...
- 201521123013 《Java程序设计》第5周学习总结
1. 本章学习总结 1.1 尝试使用思维导图总结有关多态和接口的知识点. 1.2可选 使用常规方法总结其他上课内容. 接口:不是类,不能使用new实例化,可用instanceof判断是否实现某接口.接 ...
- Java课程设计—学生成绩管理系统
一. 团队名称.团队成员介绍(需要有照片) 团队名称:进击的712 团队成员 杨雪莹[组长] 201521123005 网络1511 林楚虹 201521123002 网络1511 董美凤 20152 ...
- 201521123103 《java学习笔记》 第十周学习总结
一.本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 二.书面作业 本次PTA作业题集异常.多线程 1.finally 题目4-2 1.1 截图你的提交结果(出现学 ...
- “.Net 社区大会”(dotnetConf) 2017 Day 1 Keynote: .NET Everywhere
8月份已经发布了.NET Core 2.0, 大会Keynote 一开始花了大量的篇幅回顾.NET Core 2.0的发布,社区的参与度已经非常高.大会的主题是.NET 无处不在: NET Core ...
- 《Head First 设计模式》读书笔记(1) - 策略模式
<Head First 设计模式>(点击查看详情) 1.写在前面的话 之前在列书单的时候,看网友对于设计模式的推荐里说,设计模式的书类别都大同小异,于是自己就选择了Head First系列 ...
- mongodb 面试题总结
mongodb 面试题总结 1 nosql和关系型数据库的区别 2 nosql数据库有哪些 redis mongodb hbase 3 MySQL与mongodb本质之间最基本的差别是什么 差别在多方 ...
- JMeter关联(正则表达式提取器)
关联:与系统交互过程中,系统返回的内容,需要在接下来的交互中用到,如防止csrf攻击而生成的token. 从前一个请求中取,用Regular Expression Extractor 正则表达式提取器 ...
- 调用惯例Calling Convention (或者说:调用约定)
调用惯例影响执行效率,参数的传递方式以及栈清除的方式. 调用惯例 参数传递顺序 谁负责清除参数 参数是否使用暂存器 register 从左到右 被调用者 是 pascal 从左到右 被调用者 否 ...