Я пытаюсь реализовать какой-то игровой движок "просто для меня", и сюжет проблемы выглядит следующим образом:
Предположим, у меня есть какой-то абстрактный интерфейс для визуализируемой сущности, например IRenderable
.
И это объявлено следующим образом:
interface IRenderable {
// (...)
// Suppose that Backend is some abstract backend used
// for rendering, and it's implementation is not important
virtual void Render(Backend& backend) = 0;
};
Сейчас я делаю что-то вроде объявления разных классов, таких как
class Ball : public IRenderable {
virtual void Render(Backend& backend) {
// Rendering implementation, that is specific for
// the Ball object
// (...)
}
};
И затем всевыглядит хорошо.Я могу легко сделать что-то вроде std::vector<IRenderable*> items
, вставить некоторые элементы, такие как new Ball()
в этот вектор, а затем сделать вызов, похожий на foreach (IRenderable* in items) { item->Render(backend); }
Хорошо, я думаю, что это «полиморфный» способ, но чтоесли я хочу иметь разные типы объектов в своей игре и возможность манипулировать их состоянием, где каждый объект может управляться через собственный интерфейс?
Я мог бы сделать что-то вроде
struct GameState {
Ball ball;
Bonus bonus;
// (...)
};
и затем легко изменять состояние объектов с помощью своих собственных методов, например ball.Move(...)
или bonus.Activate(...)
, где Move(...)
характерно только для Ball
и Activate(...)
- только для Bonus
экземпляров.
Но в этом случае я теряю возможность писать foreach IRenderable*
просто потому, что храню эти шары и бонусы как экземпляры их производных, а не базовых классов.И в этом случае процедура рендеринга превращается в беспорядок, подобный
ball.Render(backend);
bonus.Render(backend);
// (...)
, и это плохо, потому что мы фактически теряем наш полиморфизм таким образом (нет реальной необходимости делать виртуальную функцию Render
и т. Д.
Другой подход означает вызов downcasting через dynamic_cast
или что-то с typeid
, чтобы определить тип объекта, которым вы хотите манипулировать, и это выглядит еще хуже для меня, и это также разрушает эту «полиморфную» идею.
Итак, мой вопрос - существует ли какой-то (вероятно) альтернативный подход к тому, что я хочу сделать, или мой текущий шаблон каким-то образом может быть изменен так, чтобы я фактически сохранил IRenderable*
для своей игры?объекты (чтобы я мог вызывать виртуальный Render
метод для каждого из них), сохраняя при этом возможность легко изменять состояние этих объектов?
Может быть, я делаючто-то абсолютно неправильно с самого начала, если да, пожалуйста, укажите это:)
Заранее спасибо!