This function saves the current state of a game to a file. It gets the path to the local app data folder and constructs a file path and name for the save. It then opens a binary file at that path, truncating any existing contents. It writes game state data like map ID, team colors, armies and their starting positions, and the list of player turns to the file. This allows resuming a game from the same point by reloading this saved data on game start up.
Cyaniclab : Software Development Agency Portfolio.pdf
Save game function
1. // this function is used to save the current game (turn by turn)
void GameBoard::SaveGamePlay()
{
// if previous save has been loaded and no extra turns have been completed
if (reviewLoaded && gamePlayList.size() <= reviewPlayList.size()) return;
// if there is nothing to save
if (gamePlayList.empty()) return;
// local variables
HANDLE hFind;
WIN32_FIND_DATA FindFileData;
wostringstream stringstream;
char path[MAX_PATH];
LPWSTR wszPath = NULL;
size_t size;
// Get the path to the app data folder
HRESULT hr = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, 0, &wszPath);
// Convert from LPWSTR to char[]
wcstombs_s(&size, path, MAX_PATH, wszPath, MAX_PATH);
// Convert char types
stringstream << path;
// variable to be used for save
wstring pathtowrite = stringstream.str();
// variable for folder search
wstring localFolder(pathtowrite.begin(), pathtowrite.end());
localFolder += L"*";
// find first valid file in folder
hFind = FindFirstFile(localFolder.c_str(), &FindFileData);
// Create our save file
if (reviewLoaded) // overwrite the 'continued' game
{
pathtowrite += L"";
pathtowrite += wstring(currSaveData.address.begin(), currSaveData.address.end());
}
else // create a new save
{
pathtowrite += L"Game_";
time_t rawtime;
struct tm * timeinfo;
char buffer[80];
// get localtime
time(&rawtime);
timeinfo = localtime(&rawtime);
// format time
strftime(buffer, 80, "%d-%m-%Y_%I%M%S", timeinfo);
// convert to wstring
string str(buffer);
wstring wStr(str.begin(), str.end());
// add time to end of filename
pathtowrite += wStr;
}
2. pathtowrite += (L".bin");
fstream out(pathtowrite.c_str(), ios_base::out | ios_base::trunc | ios_base::binary);
if (out.is_open())
{
// create local variables to be saved
unsigned int mapID = theNetwork->GetMapID();
XMFLOAT4 team1Color = player[0]->GetColor();
XMFLOAT4 team2Color = player[1]->GetColor();
vector<Unit*> team1Army = player[0]->GetArmy();
vector<Unit*> team2Army = player[1]->GetArmy();
unsigned int team1Size = team1Army.size();
unsigned int team2Size = team2Army.size();
unsigned int numLists = gamePlayList.size();
// determine if an AI is being used
unsigned int teamAI = 0;
if (GetSpecificPlayer(0)->IsUsingAI())
{
teamAI = 1;
if (GetSpecificPlayer(1)->IsUsingAI())
teamAI = 3;
}
else if (GetSpecificPlayer(1)->IsUsingAI())
teamAI = 2;
// save base gamestate data
out.write((const char*)&mapID, sizeof(mapID));
out.write((const char*)&teamAI, sizeof(teamAI));
out.write((const char*)&numLists, sizeof(numLists));
out.write((const char*)&team1Color, sizeof(team1Color));
out.write((const char*)&team2Color, sizeof(team2Color));
// save army 1
out.write((const char*)&team1Size, sizeof(team1Size));
unsigned int count = 0;
for (auto const& unit : team1Army)
{
unitType type = unit->GetType();
unsigned int unitID = unit->GetID();
unsigned int sqID = army1StartLocs[count++];
out.write((const char*)&type, sizeof(type));
out.write((const char*)&unitID, sizeof(unitID));
out.write((const char*)&sqID, sizeof(sqID));
}
// save army 2
out.write((const char*)&team2Size, sizeof(team2Size));
count = 0;
for (auto const& unit : team2Army)
{
unitType type = unit->GetType();
unsigned int unitID = unit->GetID();
unsigned int sqID = army2StartLocs[count++];
out.write((const char*)&type, sizeof(type));
out.write((const char*)&unitID, sizeof(unitID));
out.write((const char*)&sqID, sizeof(sqID));
}
// save current Game (player turns)
for (auto const& list : gamePlayList)
{
unsigned int numActions = list.size();
out.write((const char*)&numActions, sizeof(numActions));
3. for each(saveData::actionData action in list)
{
ActionType type = action.type;
unsigned int unitID = action.unitID;
unsigned int dir = action.direction;
unsigned int dist = action.distance;
out.write((const char*)&type, sizeof(type));
out.write((const char*)&unitID, sizeof(unitID));
out.write((const char*)&dir, sizeof(dir));
out.write((const char*)&dist, sizeof(dist));
unsigned int size = action.destSquares.size();
out.write((const char*)&size, sizeof(size));
for (unsigned int loop = 0; loop < size; loop++)
{
unsigned int id = action.destSquares[loop];
out.write((const char*)&id, sizeof(id));
}
}
}
out.close();
}
}