Я пытаюсь выполнить какое-то «только-для-меня» игровой движок и сюжет этой проблемы идет следующим образом:C++ игры проектирование и полиморфизм вопрос
Предположит, у меня есть некоторый абстрактный интерфейс для визуализируемого объекта , например 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
функции виртуальной и т.д.
Другого подхода означает применение понижающего приведения через dynamic_cast
или что-то с typeid
, чтобы определить тип объекта, который вы хотите управлять, и это выглядит еще хуже для меня, и это также нарушает эту «полиморфную» идею.
Итак, мой вопрос - есть ли какой-то (возможно) альтернативный подход к тому, что я хочу сделать, или мой текущий шаблон может быть каким-то образом изменен, так что я бы фактически хранили IRenderable*
для своих игровых объектов (чтобы я мог вызывать виртуальный метод Render
для каждого из них) сохраняя при этом способность легко изменять состояние этих объектов?
Может быть, я делаю что-то совершенно неправильно с самого начала, если это так, пожалуйста, укажите это :)
Спасибо заранее!
Знает ли кто-нибудь некоторый эффективный способ C++ для реализации второго цикла через эти элементы Renderable, что приводит к обнаружению подмножества подвижных объектов? Либо я просто глуп, либо это можно сделать только путем вызова динамического casting/typeid/собственной реализации RTTI ... Спасибо за ответ :) –
@ Kotti просто создайте другой список из них. Например. у вас есть список Renderables, список Movables, список коллекционирования. Затем в любое время, когда вы хотите работать с любым подмножеством, просто перейдите к соответствующему списку. (Снова добавьте Renderables в отображаемый список в конструкторе Renderable.) –