Jump to content

aiaf's Blog

  • entries
    11
  • comments
    4
  • views
    7,354

Storing game data (using sqlite3)


aiaf

1,403 views

 Share

Didn't post here in a long time , this will be about storing game data.

There are  a lot of options on how to store your game data structures:

  • files (json,xml,yaml , custom etc)
  • databases , nosql dbs
  • memory (if no persistence needed)

Also if you use an engine it could provide its own way of storing data.

Choosing a good way to do persistence is important.

This depends on lots of factors like game type, complexity of data structures etc

 

Ill describe below a way to use the sqlite3 database:

https://www.sqlite.org/index.html

 

Some code i wrote that generates a class with support for sqlite3 database persistence:

https://gist.github.com/aiafrasinei/65cb2cfeeb417459e0ab927302168abc

 

Example how to use:

SqlHt::GetInstance().Generate("Config title_s height_i width_i fullscreen_i vsync_i", true, true, false);

This will generate the file Config,h with this code :

class Config
{

private:
    sqlite3 *db;
    char* zErrMsg = 0;

protected:

public:
    string Title;
    int Height;
    int Width;
    int Fullscreen;
    int Vsync;

    Config(string Title, int Height, int Width, int Fullscreen, int Vsync) {
        filesystem::path p("Config.db");
        if(filesystem::file_size(p) == 0) {
            string sql = "CREATE TABLE Config ( ID INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, TITLE TEXT, HEIGHT INTEGER, WIDTH INTEGER, FULLSCREEN INTEGER, VSYNC INTEGER )";
            char * sql_const = const_cast<char*>(sql.c_str());
            sqlite3_exec_ec(db, sql_const, zErrMsg);

            string insert_sql = "INSERT INTO Config ( ID, TITLE, HEIGHT, WIDTH, FULLSCREEN, VSYNC) VALUES (NULL,'" + Title + "', " + to_string(Height) + ", " + to_string(Width) + ", " + to_string(Fullscreen) + ", " + to_string(Vsync) + ")";
            char * insert_sql_const = const_cast<char*>(insert_sql.c_str());
            sqlite3_exec_ec(db, insert_sql_const, zErrMsg);
        } else {
            int rc = sqlite3_open("Config.db", &db);
        }

        sqlite3_stmt* stmt = NULL;

        string select_sql = "SELECT * FROM Config";
        int ret = sqlite3_prepare_v2(db, select_sql.c_str(), -1, &stmt, NULL);
        if (ret != SQLITE_OK) {
            string err(zErrMsg);
            cout << "Nothing to select, db should contain at least one entry" << endl;
            sqlite3_free(zErrMsg);
        }

        ret = sqlite3_step(stmt);
        while (ret != SQLITE_DONE && ret != SQLITE_OK) {
            int colCount = sqlite3_column_count(stmt);
            for (int colIndex = 0; colIndex < colCount; colIndex++) {
                int type = sqlite3_column_type(stmt, colIndex);
                const char* columnName = sqlite3_column_name(stmt, colIndex);
                string cns = columnName;
                if (type == SQLITE_INTEGER) {
                    int valInt = sqlite3_column_int(stmt, colIndex);
                    if(cns == "HEIGHT") {
                        this->Height = valInt;
                    }
                    if(cns == "WIDTH") {
                        this->Width = valInt;
                    }
                    if(cns == "FULLSCREEN") {
                        this->Fullscreen = valInt;
                    }
                    if(cns == "VSYNC") {
                        this->Vsync = valInt;
                    }
                }

                if (type == SQLITE_TEXT) {
                    const unsigned char *text = sqlite3_column_text(stmt, colIndex);
                    if(cns == "TITLE") {
                        this->Title = string(reinterpret_cast<const char*>(text));
                    }
                }
            }
            ret = sqlite3_step(stmt);
        }
        ret = sqlite3_finalize(stmt);
    }

    Config() {
    }

    ~Config() {
        sqlite3_free(zErrMsg);
        sqlite3_close(db);
    }

    sqlite3 *GetDb() {
        return db;
    }

    bool Persist() {
        string update_sql= "UPDATE Config SET TITLE='" + this->Title + "', HEIGHT='" + to_string(this->Height) + "', WIDTH='" + to_string(this->Width) + "', FULLSCREEN='" + to_string(this->Fullscreen) + "', VSYNC='" + to_string(this->Vsync) + "'";
        char * update_sql_const = const_cast<char*>(update_sql.c_str());
        return sqlite3_exec_ec(db, update_sql_const, zErrMsg);
    }

    bool Persist(string Title, int Height, int Width, int Fullscreen, int Vsync) {
        string update_sql= "UPDATE Config SET TITLE='" + Title + "', HEIGHT='" + to_string(Height) + "', WIDTH='" + to_string(Width) + "', FULLSCREEN='" + to_string(Fullscreen) + "', VSYNC='" + to_string(Vsync) + "'";
        char * update_sql_const = const_cast<char*>(update_sql.c_str());
        int rc = sqlite3_exec_ec(db, update_sql_const, zErrMsg);

        this->Title=Title;
        this->Height=Height;
        this->Width=Width;
        this->Fullscreen=Fullscreen;
        this->Vsync=Vsync;
        
        if(rc != 0) {
            return false;
        } else {
            return true;
        }
    }

};

This way you can generate the data structures for your game that can be saved to disk.

Also sqlite3 support in memory databases.

Purpose of this article is to present some idea on how to store game data.

  • Like 2
 Share

0 Comments


Recommended Comments

There are no comments to display.

Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...