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, 0, sizeof(udata));
    }
    SSqlData(enSqlTableType ntable, enSqlDataType ntype, std::string name)
        :nSqlTableType(ntable), nSqlDataType(ntype), sSqlDataName(name)
    {
        memset(&udata, 0, 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(0)
{
    // 初始化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 ? 1 : 0);
    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 = 100;

    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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM