I did some searching on the forum for this and the only thing people mention is to do some kind of versioning.
How can I implement a save/load system so that I can load old saved maps.Currently I have a world class which has a map class member.There is no data in the world class to be saved the map class is the class that I want to save - restore.
Here is the world class :
class World
{
public:
World(DAEnginePtr engine);
~World();
//
// Loads a map from the disk to the Map member
//
void loadMap(DARendererPtr renderer,const std::string& filename);
//
// Saves the map member to the disk
//
void saveMap(const std::string& filename)const;
//
// Frees all D3DPOOL_DEFAULT resources
// Calls onLostDevice on member objects
//
void onLostDevice();
//
// After lost device create resources again
// Calls onResetDevice on member objects
//
void onResetDevice(DARenderer* renderer);
//
// Update world
// Calls map update
//
void update(DARenderer* renderer,float elapsedTime);
void setMap(boost::shared_ptr<Map> map){m_Map = map;}
boost::shared_ptr<Map> getMap(){return m_Map;}
private:
/*
* Current map
*/
boost::shared_ptr<Map> m_Map;
/*
* Loads the shaders used by the game and the editor
*/
void loadShaders(DAEngine* engine);
void loadTextures(DAEngine* engine);
void loadModels(DAEngine* engine);
};
And the map class :
class Map
{
public:
// Creates the map according to the tMapCreateParams
Map(boost::shared_ptr<DARenderer> renderer,const tMapCreateParams* params);
// Creates the map from a file on the disk
Map(DARendererPtr renderer,const std::string& filename);
//destructor
~Map();
//
// Save this map object to file
//
void save(const std::string& filename);
//
// Save all entities to file
//
void saveEntities(std::ofstream& file);
// Updates game objects,detect visibilities
void update(DARenderer* renderer,float elapsedTime);
// Processes collisions between game objects(camera-terrain etc.)
void processCollisions(DARenderer* renderer,float elapsedTime);
//Places forest on the map.Randomly selects forestCount locations
//and puts treeCount trees around that location
void placeForest(boost::shared_ptr<DARenderer> renderer,
const STMath::Vector3& forestPosition,
UINT treeCount,UINT forestRadius,
STWin::ProgressBar *progressBar);
/*
* Changes the sealevel of the map
*/
void changeSeaLevel(float newSeaLevel);
/*
* Called when the d3d device is lost
* frees D3DPOOL_DEFAULT resources
*/
void onLostDevice();
/*
* Called when the d3d devices is reset
* recreates D3DPOOL_DEFAULT resources
*/
void onResetDevice(DARenderer* renderer);
//Entity
void addEntity(boost::shared_ptr<Entity> addEntity);
void deleteEntity(const Entity* entity);
boost::shared_ptr<Entity> getEntity(int entity)const {return m_Entities[entity];}
boost::shared_ptr<Entity> getVisibleEntity(int entity)const {return m_VisibleEntities[entity];}
size_t getEntityCount()const {return m_Entities.size();}
size_t getVisibleEntityCount() const{return m_VisibleEntities.size();}
//Data Access
//set/get Name
void setName(const std::string& name){m_Name = name;}
const std::string& getName()const{return m_Name;}
boost::shared_ptr<GeoMipmapTerrain> getTerrain(){return m_Terrain;}
boost::shared_ptr<Water> getWater(){return m_Water;}
boost::shared_ptr<SkyPlane> getSkyPlane(){return m_SkyPlane;}
//static data
static const float MorningColor[4];
protected:
//
// name of the map appearing ingame
//
std::string m_Name;
//
// the terrain of this map
//
boost::shared_ptr<GeoMipmapTerrain> m_Terrain;
//
// The water of the map(null if map does not have water)
//
boost::shared_ptr<Water> m_Water;
//
// The skyplane over the map
//
boost::shared_ptr<SkyPlane> m_SkyPlane;
//
// Entities on the map
//
std::vector<boost::shared_ptr<Entity>> m_Entities;
//
// visible entities.(filled inside Map::update)
//
std::vector<boost::shared_ptr<Entity>> m_VisibleEntities;
};
As you can see the map class holds the other objects and they will need to get saved too.
Anyway first I was thinking of giving each class a save load method or make another contructor for the class which constructs the object from a file or data stream.But I don't know how to handle old save games in this approach.
So I thought I could write a SaveLoadManager class which saves loads the world.
This class can have different save/load method pairs for different versions of save files.For example :
class SaveLoadManager
{
public:
void load(World* world,const std::string& filename);
void save(World* world,const std::string& filename,int version);
void save_version_1(World* world,const std::string& filename);
void load_version_1(World* world,const std::string& filename);
void save_version_2(World* world,const std::string& filename);
void load_version_2(World* world,const std::string& filename);
};
//implementation
void SaveLoadManager::load(World* world,const std::string& filename)
{
get version from file
call the appropriate load_version_*() function
}
void SaveLoadManager::save(World* world,const std::string& filename,int version)
{
write version number to file
call the appropriate save_version_*() function
}
Each time I change map,world,terrain I would need a new save_version_* and a save_version_* to save load that new states.Also I would need to write the save file version to the file and call the appropriate load_version_* function.
Another problem with this is once I saved some maps with a save/load pair I must not change them again or the maps saved before will be broken.
This looks like a very clumsy way of saving loading.So what can I do fellows?
Edit:Also this will create lots of code duplication in the save_version_* load_version_* methods. :|