C ++: сделать полную копию вектора указателей - PullRequest
0 голосов
/ 09 ноября 2011

Я работаю над игрой на C ++. Мои объекты уровня находятся в векторе (объект является суперклассом для объектов моего уровня).

Мне нужно, чтобы состояние этого вектора было сохранено на контрольных точках и восстановлено при смерти.

Итак, в начале уровня создается вектор (объекты) (old_objects).

Если вы нажмете контрольную точку, старые_объекты будут стерты, а объекты повторно скопированы в старые_объекты.

Если вы умрете, данные из объектов стираются, а old_objects копируется обратно в объекты.

Я пытался сделать это несколькими способами, но я не смог заставить его работать. Помощь

РЕДАКТИРОВАТЬ: я пытался использовать виртуальный метод clone (). Он выбрасывает из диапазона ошибок.

class Object {
  public:
    virtual Object* clone() { return new Object(); }
};

class SubObjectA {
  public:
    Object* clone() { return new SubObjectA(datablahblah); }
};

class SubObjectB {
  public:
    Object* clone() { return new SubObjectB(datablahblah); }
};

for (vector<Object*>::iterator it = objects.begin(); it != objects.end(); it++) {
    Object* tempobj = *it;
    old_objects.push_back(tempobj->clone());
}

Но все, что я получаю, это то же самое:

terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

Ответы [ 2 ]

1 голос
/ 09 ноября 2011

Вы можете использовать шаблон Prototype и сделать так, чтобы ваш базовый класс Object объявил чисто виртуальный метод clone ().Затем во время контрольной точки вам просто нужно перебрать вектор, вызывающий клон по указателям и вставив их в новый вектор.

0 голосов
/ 09 ноября 2011

Единственное важное требование здесь - предоставить конструктор глубокого копирования, который хранит всю необходимую информацию (или, если это невозможно, метод для получения всей необходимой информации). Затем используйте этот ctor / метод для создания второго вектора. Что-то вроде:

class Object
{
    RenderObject * m_Renderable;
    int m_Health;
    float3 m_Position;

    Object(const Object * other) :
       m_Renderable(nullptr),
       m_Health(other->m_Health), 
       m_Position(other->m_Position)
    { };

    Object * GetStorable()
    {
        return new Object(*this);
    }
};

, чтобы сохранить «контрольные точки», вы просто делаете:

vector<vector<shared_ptr<Object>>> gCheckpoints;
vector<shared_ptr<Object>> gLevelObjects;

vector<shared_ptr<Object>> checkpoint;
std::for_each(
    gLevelObjects.begin(), gLevelObjects.end(),
    [&](shared_ptr<Object> obj)
    {
        checkpoint.push_back(obj->GetStorable());
    });
gCheckpoints.push_back(checkpoint); // creates a new checkpoint

Вам нужно будет воссоздать информацию рендеринга для объектов при восстановлении контрольной точки; однако это требование для большинства систем сохранения в большинстве графических контекстов.

В зависимости от того, как настроен ваш класс Object, вы также можете наследовать от другого класса, который состоит из только хранимых данных, и просто сохранять их и создавать из них визуализируемые при необходимости (class RenderObject : StoredObject { ... };).

Вы можете альтернативно сериализовать объекты некоторым способом (двоичное сохранение, xml, json) и сохранить их в файл (автосохранение / быстрое сохранение / контрольная точка) или в памяти, а затем использовать обычный механизм загрузки для загрузки этого конкретного файла. .

Лучший метод зависит от того, каковы ваши планы и как настроена ваша система, но эта концепция должна обеспечить основы или дать вам отправную точку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...