javascript
Qt文档阅读笔记-对JSON Save Game官方实例解析
程序運(yùn)行截圖如下:
JSON Save Game例子展示了如何使用QJsonDocument,QJsonObject,QJsonArray保存和加載存檔。
許多游戲有存儲的功能,允許玩家存儲保存游戲進(jìn)度或者加載存檔。在存儲游戲,通常將每個游戲?qū)ο笮蛄械揭粋€文件中。存儲的文件格式有多種多樣。其中的一種方式就是使用Json格式,使用的是QJsonDocument,如果希望文件不可讀,那么可以將其轉(zhuǎn)換為二進(jìn)制,這里可以再來個對稱加密,更好。
此例子展示了如何存儲文件,并且加載json文件。
?
Character類
角色類代表游戲里面的NPC。還存儲了玩家名字,等級,職業(yè)等。
此類還提供了read()和write()方法去序列化其成員變量。
class Character{Q_GADGET;public:enum ClassType {Warrior, Mage, Archer};Q_ENUM(ClassType)Character();Character(const QString &name, int level, ClassType classType);QString name() const;void setName(const QString &name);int level() const;void setLevel(int level);ClassType classType() const;void setClassType(ClassType classType);void read(const QJsonObject &json);void write(QJsonObject &json) const;void print(int indentation = 0) const;private:QString mName;int mLevel;ClassType mClassType;};上述的代碼主要關(guān)心read和write函數(shù)的實(shí)現(xiàn)
void Character::read(const QJsonObject &json){if (json.contains("name") && json["name"].isString())mName = json["name"].toString();if (json.contains("level") && json["level"].isDouble())mLevel = json["level"].toInt();if (json.contains("classType") && json["classType"].isDouble())mClassType = ClassType(json["classType"].toInt());}read()函數(shù),使用QJsonObject獲取值填充到Character中。可以使用QJsonObject::operator[]或QJsonObject::value()。如果返回的值不存在則為QJsonValue::Undefined。可以使用QJsonObject::contains()確保其key值存在。
void Character::write(QJsonObject &json) const{json["name"] = mName;json["level"] = mLevel;json["classType"] = mClassType;}write()函數(shù)與read()函數(shù)相反,使用QObject::operator[]()和QJsonObject::insert()進(jìn)行賦值,如果key存在,那么值將會被覆蓋。
下面是Level類:
class Level{public:Level() = default;Level(const QString &name);QString name() const;QVector<Character> npcs() const;void setNpcs(const QVector<Character> &npcs);void read(const QJsonObject &json);void write(QJsonObject &json) const;void print(int indentation = 0) const;private:QString mName;QVector<Character> mNpcs;};游戲中還需要等級,每一個npc也需要等級,使用QVector存儲Character對象,然后再提供上面類似的read()和write()函數(shù)。
void Level::read(const QJsonObject &json){if (json.contains("name") && json["name"].isString())mName = json["name"].toString();if (json.contains("npcs") && json["npcs"].isArray()) {QJsonArray npcArray = json["npcs"].toArray();mNpcs.clear();mNpcs.reserve(npcArray.size());for (int npcIndex = 0; npcIndex < npcArray.size(); ++npcIndex) {QJsonObject npcObject = npcArray[npcIndex].toObject();Character npc;npc.read(npcObject);mNpcs.append(npc);}}}使用QJsonArray接受json中的數(shù)組,調(diào)用toObject(0獲取Character的Json對象。然后存儲到mNpcs中。
void Level::write(QJsonObject &json) const{json["name"] = mName;QJsonArray npcArray;for (const Character &npc : mNpcs) {QJsonObject npcObject;npc.write(npcObject);npcArray.append(npcObject);}json["npcs"] = npcArray;}這個是寫函數(shù)。
上面就是人物和等級相關(guān)的類,下面是游戲類。
class Game{public:enum SaveFormat {Json, Binary};Character player() const;QVector<Level> levels() const;void newGame();bool loadGame(SaveFormat saveFormat);bool saveGame(SaveFormat saveFormat) const;void read(const QJsonObject &json);void write(QJsonObject &json) const;void print(int indentation = 0) const;private:Character mPlayer;QVector<Level> mLevels;};首先定義了SaveFormat的枚舉,可以選擇存儲為Json或者二進(jìn)制。提供了玩家和關(guān)卡相關(guān)的成員變量,這里官方給出了下面3個函數(shù)的說明:newGame(),saveGame(),loadGame(),這里read()和write()函數(shù)被saveGame()和loadGame()使用。
void Game::newGame(){mPlayer = Character();mPlayer.setName(QStringLiteral("Hero"));mPlayer.setClassType(Character::Archer);mPlayer.setLevel(QRandomGenerator::global()->bounded(15, 21));mLevels.clear();mLevels.reserve(2);Level village(QStringLiteral("Village"));QVector<Character> villageNpcs;villageNpcs.reserve(2);villageNpcs.append(Character(QStringLiteral("Barry the Blacksmith"),QRandomGenerator::global()->bounded(8, 11),Character::Warrior));villageNpcs.append(Character(QStringLiteral("Terry the Trader"),QRandomGenerator::global()->bounded(6, 8),Character::Warrior));village.setNpcs(villageNpcs);mLevels.append(village);Level dungeon(QStringLiteral("Dungeon"));QVector<Character> dungeonNpcs;dungeonNpcs.reserve(3);dungeonNpcs.append(Character(QStringLiteral("Eric the Evil"),QRandomGenerator::global()->bounded(18, 26),Character::Mage));dungeonNpcs.append(Character(QStringLiteral("Eric's Left Minion"),QRandomGenerator::global()->bounded(5, 7),Character::Warrior));dungeonNpcs.append(Character(QStringLiteral("Eric's Right Minion"),QRandomGenerator::global()->bounded(4, 9),Character::Warrior));dungeon.setNpcs(dungeonNpcs);mLevels.append(dungeon);}初始化函數(shù)設(shè)置了玩家目前在哪個關(guān)卡和相關(guān)屬性以及NPC。
void Game::read(const QJsonObject &json){if (json.contains("player") && json["player"].isObject())mPlayer.read(json["player"].toObject());if (json.contains("levels") && json["levels"].isArray()) {QJsonArray levelArray = json["levels"].toArray();mLevels.clear();mLevels.reserve(levelArray.size());for (int levelIndex = 0; levelIndex < levelArray.size(); ++levelIndex) {QJsonObject levelObject = levelArray[levelIndex].toObject();Level level;level.read(levelObject);mLevels.append(level);}}}read()函數(shù)填充mPlayer相關(guān)的數(shù)據(jù),然后清空關(guān)卡然后重置下。
通過讀取QJsonArray讀取每個關(guān)卡的數(shù)據(jù)。
void Game::write(QJsonObject &json) const{QJsonObject playerObject;mPlayer.write(playerObject);json["player"] = playerObject;QJsonArray levelArray;for (const Level &level : mLevels) {QJsonObject levelObject;level.write(levelObject);levelArray.append(levelObject);}json["levels"] = levelArray;}這里的write和上面說的一樣。
bool Game::loadGame(Game::SaveFormat saveFormat){QFile loadFile(saveFormat == Json? QStringLiteral("save.json"): QStringLiteral("save.dat"));if (!loadFile.open(QIODevice::ReadOnly)) {qWarning("Couldn't open save file.");return false;}QByteArray saveData = loadFile.readAll();QJsonDocument loadDoc(saveFormat == Json? QJsonDocument::fromJson(saveData): QJsonDocument::fromBinaryData(saveData));read(loadDoc.object());QTextStream(stdout) << "Loaded save for "<< loadDoc["player"]["name"].toString()<< " using "<< (saveFormat != Json ? "binary " : "") << "JSON...\n";return true;}加載游戲的關(guān)鍵是存儲的什么格式的文件,是save.json還是save.dat這個文件
QJsonDocument可以通過使用QJsonDocument::fromJson()和QJsonDocument::fromBinaryData()讀取數(shù)據(jù)。成功就返回true。
bool Game::saveGame(Game::SaveFormat saveFormat) const{QFile saveFile(saveFormat == Json? QStringLiteral("save.json"): QStringLiteral("save.dat"));if (!saveFile.open(QIODevice::WriteOnly)) {qWarning("Couldn't open save file.");return false;}QJsonObject gameObject;write(gameObject);QJsonDocument saveDoc(gameObject);saveFile.write(saveFormat == Json? saveDoc.toJson(): saveDoc.toBinaryData());return true;}存儲游戲和loadGame()很像通過官方封裝好的QJsonDocument::toJson()和JSonDocument::toBinarayData()存儲,一個是讀Json,一個是讀二進(jìn)制。
下面是main()函數(shù):
int main(int argc, char *argv[]){QCoreApplication app(argc, argv);QStringList args = QCoreApplication::arguments();bool newGame = true;if (args.length() > 1)newGame = (args[1].toLower() != QStringLiteral("load"));bool json = true;if (args.length() > 2)json = (args[2].toLower() != QStringLiteral("binary"));Game game;if (newGame)game.newGame();else if (!game.loadGame(json ? Game::Json : Game::Binary))return 1;// Game is played; changes are made...QTextStream(stdout) << "Game ended in the following state:\n";game.print();if (!game.saveGame(json ? Game::Json : Game::Binary))return 1;return 0;}?
總結(jié)
以上是生活随笔為你收集整理的Qt文档阅读笔记-对JSON Save Game官方实例解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PHP笔记-文件上传例子
- 下一篇: Python笔记-使用cython生成d