Jump to content

  • Log In with Google      Sign In   
  • Create Account

#ActualBeerNutts

Posted 06 January 2013 - 11:53 AM


Let me give you an example Save load for a simple Pet Game.

 

Let's assume you have a Pet class.  In this class it has the pet's age (based on days), it's health, and it's happiness.  let's also assume it has an inventory of items which are unique based on some unique int ID.  Let's also add a Save() and Load() function. At it's definition, it may look like this:

 

 

 
#include "TItem.h"
 
enum THappiness {
  SAD_PET,
  CONTENT_PET,
  HAPPY_PET
};
 
class TPet {
private:
  int Age;
  int Health;
  std::string Name;
 
  THappiness Happiness;
  std::vector<TItems> Inventory;
 
public:
  TPet(std::string petName);
  ~TPet();
 
  void AddItem(TItem item);
  std::vector<TItems> GetInventory();
  std::string GetName();
 
  int GetHealth();
  void Sethealth(int Health);
 
  int GetAge();  
  void IncreamentAge();
 
  THappiness GetHappiness();
  void SetHappiness(THappiness happiness);
  
  void Load(std::string saveFileName);
  void Save(std::string saveFileName);  
};

 

 

I'm not going to worry about the other files, and no go into detail about reading and writing to files (nor loops), but your save and load would do something like this (in Pseudo-code):

 

void TPet::Save(std::string saveFileName)
{
  FileType saveFile = FileOpen(saveFileName);
 
  // We know Age Health and happiness will always be the same length, so we can write them in without
  // having to write in the length of the data
  WriteFile(saveFile, &Age, sizeof(Age));
  WriteFile(saveFile, &Health, sizeof(Health));
  WriteFile(saveFile, &Happiness, sizeof(Happiness));
 
  // Store the Name, but give it the name length 1st
  int length = Name.size();
  WriteFile(saveFile, &length, sizeof(length));
  // loop through and write each character
 
  // Now write the number of inventory items
  length = Inventory.size();
  WriteFile(saveFile, &length, sizeof(length));
  // now loop through and store each item id, assuming you can access TItem::GetId()
 
  CloseFile(saveFile);
}
 
// In load you do the same thing in the same order

 

I got a related question to this. Can't you just write a whole instance of a object to the binary file, and then load a full object with a load function? Or am I missing something?

 

No, you can't.  In the class, there are instances of std::string, and a Vector Of Items being stored.  What is actually stored for those values in the class instance is only an address. So, you need to explicitly store each of those items (the character's in the string, and the inventory items stores in the vector).


#2BeerNutts

Posted 06 January 2013 - 11:53 AM

 

Let me give you an example Save load for a simple Pet Game.

 

Let's assume you have a Pet class.  In this class it has the pet's age (based on days), it's health, and it's happiness.  let's also assume it has an inventory of items which are unique based on some unique int ID.  Let's also add a Save() and Load() function. At it's definition, it may look like this:

 

 

 
#include "TItem.h"
 
enum THappiness {
  SAD_PET,
  CONTENT_PET,
  HAPPY_PET
};
 
class TPet {
private:
  int Age;
  int Health;
  std::string Name;
 
  THappiness Happiness;
  std::vector<TItems> Inventory;
 
public:
  TPet(std::string petName);
  ~TPet();
 
  void AddItem(TItem item);
  std::vector<TItems> GetInventory();
  std::string GetName();
 
  int GetHealth();
  void Sethealth(int Health);
 
  int GetAge();  
  void IncreamentAge();
 
  THappiness GetHappiness();
  void SetHappiness(THappiness happiness);
  
  void Load(std::string saveFileName);
  void Save(std::string saveFileName);  
};

 

 

I'm not going to worry about the other files, and no go into detail about reading and writing to files (nor loops), but your save and load would do something like this (in Pseudo-code):

 

void TPet::Save(std::string saveFileName)
{
  FileType saveFile = FileOpen(saveFileName);
 
  // We know Age Health and happiness will always be the same length, so we can write them in without
  // having to write in the length of the data
  WriteFile(saveFile, &Age, sizeof(Age));
  WriteFile(saveFile, &Health, sizeof(Health));
  WriteFile(saveFile, &Happiness, sizeof(Happiness));
 
  // Store the Name, but give it the name length 1st
  int length = Name.size();
  WriteFile(saveFile, &length, sizeof(length));
  // loop through and write each character
 
  // Now write the number of inventory items
  length = Inventory.size();
  WriteFile(saveFile, &length, sizeof(length));
  // now loop through and store each item id, assuming you can access TItem::GetId()
 
  CloseFile(saveFile);
}
 
// In load you do the same thing in the same order

 

I got a related question to this. Can't you just write a whole instance of a object to the binary file, and then load a full object with a load function? Or am I missing something?

 

No, you can't.  In the class, there are instances of std::string, and a Vector Of Items being stored.  What is actually stored for those values in the class instance is only an address. So, you need to explicitly store each of those items (the character's in the string, and the inventory items stores in the vector).


#1BeerNutts

Posted 06 January 2013 - 11:52 AM

Yes, that you have absolutely no idea how the data is stored internally (there could be padding or not) and even changing compiler settings could override that (which is why some compilers have #pragmas to override this).

 

That example still makes a mistake though as it completely ignores the endianess of the system. Save a file in a little endian system then try to load it in a big endian system... you won't like it (this only matters for portability reasons, but there's not much of an excuse to avoid it). Also you the size of the variable types may change (e.g. a common recent case would be 32-bit vs 64-bit). You'll need to write individual bytes to work around that (then at least you can be guaranteed in which order they'll be stored in the file and with what size).

 

EDIT: oh, also even if none of the above was an issue, what if you change the object for whatever reason, e.g. to add a new variable or something? If you save the object as-is, suddenly old saves won't be usable anymore.

 

 

Let me give you an example Save load for a simple Pet Game.

 

Let's assume you have a Pet class.  In this class it has the pet's age (based on days), it's health, and it's happiness.  let's also assume it has an inventory of items which are unique based on some unique int ID.  Let's also add a Save() and Load() function. At it's definition, it may look like this:

 

 

 
#include "TItem.h"
 
enum THappiness {
  SAD_PET,
  CONTENT_PET,
  HAPPY_PET
};
 
class TPet {
private:
  int Age;
  int Health;
  std::string Name;
 
  THappiness Happiness;
  std::vector<TItems> Inventory;
 
public:
  TPet(std::string petName);
  ~TPet();
 
  void AddItem(TItem item);
  std::vector<TItems> GetInventory();
  std::string GetName();
 
  int GetHealth();
  void Sethealth(int Health);
 
  int GetAge();  
  void IncreamentAge();
 
  THappiness GetHappiness();
  void SetHappiness(THappiness happiness);
  
  void Load(std::string saveFileName);
  void Save(std::string saveFileName);  
};

 

 

I'm not going to worry about the other files, and no go into detail about reading and writing to files (nor loops), but your save and load would do something like this (in Pseudo-code):

 

void TPet::Save(std::string saveFileName)
{
  FileType saveFile = FileOpen(saveFileName);
 
  // We know Age Health and happiness will always be the same length, so we can write them in without
  // having to write in the length of the data
  WriteFile(saveFile, &Age, sizeof(Age));
  WriteFile(saveFile, &Health, sizeof(Health));
  WriteFile(saveFile, &Happiness, sizeof(Happiness));
 
  // Store the Name, but give it the name length 1st
  int length = Name.size();
  WriteFile(saveFile, &length, sizeof(length));
  // loop through and write each character
 
  // Now write the number of inventory items
  length = Inventory.size();
  WriteFile(saveFile, &length, sizeof(length));
  // now loop through and store each item id, assuming you can access TItem::GetId()
 
  CloseFile(saveFile);
}
 
// In load you do the same thing in the same order

 

I got a related question to this. Can't you just write a whole instance of a object to the binary file, and then load a full object with a load function? Or am I missing something?

 

No, you can't.  In the class, there are instances of std::string, and a Vector Of Items being stored.  What is actually stored for those values in the class instance is only an address. So, you need to explicitly store each of those items (the character's in the string, and the inventory items stores in the vector).


PARTNERS