Im trying to make a level loading system, where the level file is stored as some binary file that has the class of the object to be spawned and its position and scale. One thing I cant figure out is how to convert a class type into something that can be written to a binary file and also retrieved later.
I tried converting it to a string, but then how do I turn that typeid(type).name() back into the class type to spawn?
Open to any methods of doing this
There are a few things going on here, so I took the liberty of writing a short snippet.
In order to read in a bunch of objects into a single container like the below when you don't know their type, they all need to derive from a base class. Alternatively you could pass the deserialize
function different vectors (or other containers) to store the different types. Whatever works.
The deserialize
function then uses a switch
like @darune suggested to construct the appropriate type.
There are all sorts of serializing / deserializing libraries out there which will allow you to be more sophisticated than this and store more complex groups of objects. I often use rapidjson for this sort of thing. boost.serialize is another option (again as @darune suggested).
#include <fstream>
#include <iostream>
#include <vector>
using std::ifstream;
using std::vector;
using std::cout;
using std::endl;
class Object
{
public:
double position;
double scale;
Object(const double& position, const double& scale)
: position(position), scale(scale) { }
virtual ~Object() {}
};
class Foo : public Object
{
public:
static const int id = 0;
Foo(const double& position, const double& scale)
: Object(position, scale) { }
};
class Bar : public Object
{
public:
static const int id = 1;
Bar(const double& position, const double& scale)
: Object(position, scale) { }
};
Object* deserialize(int id, const double& position, const double& scale)
{
switch (id)
{
case Foo::id:
return new Foo(position, scale);
case Bar::id:
return new Bar(position, scale);
default:
return nullptr;
};
}
And then an example of reading in from a text file looks like
int main(void)
{
vector<Object*> objects;
ifstream fin;
fin.open("objects.txt");
if (!fin)
throw std::runtime_error("Unable to open file");
// Read in the id, position and scale from a file
int id;
double position, scale;
while (!fin.eof())
{
fin >> id >> position >> scale;
Object* object = deserialize(id, position, scale);
if (object != nullptr)
objects.push_back(object);
}
fin.close();
// Print out the objects
for (auto pobj: objects)
cout << pobj->position << " " << pobj->scale << endl;
// Don't forget to clean up
for (auto object: objects)
delete object;
}
In this case objects.txt was a text file that is just whitespace delimited id position scale
(with no header). For example
1 0.4 10
0 0.1 5
0 0.1 1
Reading in from binary is similar.