You can either write your own save format and save file reader & writer, or use an existing parser like an XML or JSON one. You can store the save data in a GameSave
class at runtime either as a tree of the file format you chose, or inside direct member variables. I myself us the latter, as then it's easier to save data (while reading becomes a bit more tricky). It also abstracts setting of the save data with the writing of the save data.
class GameSave
{
public:
GameSave() { }
GameSave(const std::string& filename)
{
// Load save data...
}
void Write(const std::string& filename)
{
// Write save data...
}
std::string CurrentLevel;
std::vector<std::pair<std::string, int>> Inventory;
// More save data...
protected:
private:
}
Here's a very basic example of what your save class could look like. The details or writing and loading and the filename management depends on if you want to support multiple saves or not, and if you want to predefine a few save slots or allow the player to chooce their own filenames etc.
So, when the player saves the game, you need to write the required data to the file. This can be done in a few ways: you could ask each object to save its own data to the file, or you could have a parent object (like your level / gamestate) save the required data. Since your data needs seem quite small, I'd go with the latter option and write something along the lines of:
void GameplayState::SaveGame()
{
GameSave save;
save.CurrentLevel = m_Level->GetName();
Player* player = m_Level->FindPlayerEntity()->GetLevel();
save.PlayerLevel = player->GetLevel();
for (InventoryItem* item : player->GetInventory()->GetItems())
save.Inventory.push_back(std::make_pair(item->Name, item->Amount));
save.KilledEnemyCount = GameStatManager::KilledEnemyCount;
save.Write(AskPlayerForSaveSelection());
}
Finally, to continue from a save, you just have to load the data in and pass it to the correct owners. This could be done by passing the whole GameSave
around, or simply by passing the required members of the save to the constructors/methods.
void GameplayState::Continue(GameSave* save)
{
// Use save data:
m_Level = new Level(save->CurrentLevel);
m_Level->CreatePlayer(save->PlayerLevel, save->Inventory);
}
This is the basic high-level architecture of a basic game save setup that I've found that worked well enough for me, when the data that I need to save is quite small and can be handled as such. Were you need more data and more dynamic data, then you'd have to start assigning unique identifiers to objects and allowing each object to save/load its own data.