Шаблон логического дизайна - PullRequest
0 голосов
/ 23 марта 2009

В игре многие сущности должны обновляться в каждом кадре. Я играю с различными моделями дизайна, чтобы достичь этого. До сих пор у меня был класс синглтон-менеджера, к которому добавляется каждый экземпляр логики. Но я рассматриваю следующее, статический список в самом классе логики. Это хорошо, так как это удалит класс из проекта. «Движок» в этом примере будет основным классом, вызывающим update_all.

class Logic
{
public:
    Logic() { all.push_back(this); }
    virtual ~Logic() { all.erase(this); }
    virtual void update(float deltatime) = 0;

private:
    friend Engine;
    static std::list<Logic*> all;
    static void update_all(float deltatime)
    {
        for (std::list::iterator i = all.begin(); i!=all.end(); ++i)
            (*i)->update(deltatime);
    }
};
  • У этого шаблона есть имя?
  • Считаете ли вы это более хорошим подходом, чем класс синглтон-менеджера?
  • Любые другие комментарии или предостережения?

Ответы [ 6 ]

2 голосов
/ 23 марта 2009

Во-первых, вам нужно использовать remove() вместо erase() (последнему потребуется итератор в качестве аргумента)

Если вы используете немного другой цикл, как

std::list<Logic*>::iterator it = all.begin();
while (it != all.end()) {
  Logic* current = *it;
  ++it;
  current->update(deltatime);
}

Вы даже можете решить проблему siukurnin , о которой говорилось (удаление объекта логики во время обновления ()). list::remove() не делает недействительными итераторы, кроме тех, которые указывают на удаленный элемент.

Помимо этого, я также голосую за то, чтобы это было изменением шаблона синглтона. И я бы посоветовал оставить исходное решение с отдельным классом управления, на тот случай, если вам понадобится два цикла с разным временем дельты или явная поддержка многопоточности (разные объекты логики в разных потоках) или что-то еще в будущем. *

По моему мнению, это общее преимущество синглтон-класса перед статическими методами (которые вы всегда можете использовать): вы можете легко увеличить свою функциональность, если захотите сделать это в будущем ...

2 голосов
/ 23 марта 2009

Вы также можете использовать шаблон наблюдателя для этого

1 голос
/ 06 июня 2009

Как правило, вы хотите проходить через каждую сущность в вашей игре каждый вызов обновления, поэтому вы можете использовать Composite pattern , где у вас будет корневой узел. После этого вы будете рекурсивно проходить через узел и вызывать метод update () каждого объекта. Из того, что я вижу из вашего кода, у вас уже есть список, но, используя составной шаблон, вы сможете создавать группы объектов, что может упростить вашу задачу.

Из того, что я понимаю, вашему движку просто нужно вызвать метод Update () корневого узла (если вы используете составной шаблон). Исходя из этого, корневой узел будет вызывать последующие узлы, используя их update (). В какой-то момент через составное дерево вы попадете на листы, которые будут знать, как правильно обновлять себя.

Вам понадобится только указатель на ваш корневой узел в вашем движке, который будет иметь функцию UpdateAll () (или что-то еще), которая затем будет вызывать rootNode-> Update (); что, в свою очередь, будет делать то, что я описал в предыдущем абзаце.

1 голос
/ 23 марта 2009

Имхо, это шаблон Observer (ср. update вызов для каждого абонента), в котором субъект оказывается Singleton.

Предостережение об отмене регистрации при обновлении наблюдателей является сложным. Я сталкивался с этим много раз.

Элегантное решение этой проблемы было подсказано в этом ответе на мой вопрос об этом: для каждого наблюдателя добавьте промежуточный «прокси», содержащий указатель на «настоящего» наблюдателя. Отмена регистрации эквивалентна замене (атомарно) указателя прокси. После обновления все прокси с нулевыми указателями можно безопасно удалить.

1 голос
/ 23 марта 2009

Я думаю, что это все еще один: "может быть только один"

Синглтон - это шаблон, концепция: вы можете реализовать его разными способами ...

Статический член класса или глобальный экземпляр - это две возможные реализации одной и той же идеи.

Вопрос в том, почему вы хотите это изменить?

0 голосов
/ 23 марта 2009

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

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

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