C++, dynamic_cast и уточнение интерфейса

111
26 мая 2021, 08:40

Я уже долго пытаюсь придумать, как можно организовать игровую механику классического Worms. Мне удалось найти разные варианты, но все они со своими клопами и абсолютно мне не нравятся. Чувствую, что существует удобное решение, но никак не могу его нащупать, поэтому - прошу помощи.

Итак, рассмотрим уровень классического Worms, он содержит:

  • Разрушаемую землю, которая к тому же используется для коллизий. Этот вопрос я решил;
  • Баллистические объекты. Будем считать, что все, кроме взрывов, является баллистикой и может взаимодействовать друг с другом и ландшафтом. Например, граната толкает червя. В классическом Worms не так, но так интереснее;
  • Взрывы. Разрушают ландшафт, толкают всю баллистику.

Для упрощения будем считать, что у юнитов нет здоровья.

В общем-то, это основное. Самое интересное заключается в том, что юниты могут обладать некоторыми особыми свойствами. Например, они могут иметь здоровье, они могут активироваться червем и т.д.

Для упрощения представим, что у нас есть только одно специальное свойство:

  • Активируется червем;

Чтобы не строить очередную Звезду Смерти, я подумал, что можно сделать примерно такое наследование:

Взаимодействие объектов строится через:

virtual void Unit::interact(Unit *_object);

Наследники дополняют поведение своих потомков, все объекты валяются в одном месте, каждый объект сам решает, что он умеет делать и как влиять на другие объекты.

Но есть проблемы.

void Ballistic::interact(Unit *_object) должен проверять, относится ли _object ко классу Ballistic.

void ActivatedByWorm::interact(Unit *_object) должен проверять, относится ли _object ко классу Worm.

И если для ActivatedByWorm это еще было позволительно, потому что объектов типа ActivatedByWorm немного, то при учете взрывов придется делать постоянные проверки при просчете баллистики. А если еще учитывать и то, что взрывы могут наносить урон тому, у чего есть здоровье... То понижающее приведение появляется во все больших и больших классах.

Поэтому, мои вопросы такие:

  1. Является ли понижающее приведение при помощи dynamic_cast хорошим способом проверить у объекта наличие определенного интерфейса?
  2. Как еще можно построить взаимодействие между объектами в моем случае? Я перепробовал кучу паттернов, и удобного способа реализации задуманного не нашел. Самое удобное и чистое - использовать dynamic_cast, но у меня есть сомнения, что это православный приемлемый способ.
READ ALSO
Ошибка при добавлении rc файлов Qt

Ошибка при добавлении rc файлов Qt

Проект был без ошибок, пока не добавила иконку приложение qt

100
Масштабирование текста на ноутбуке

Масштабирование текста на ноутбуке

Веду некий проект, недавно прикупил ноутбук для работы вне дома, сегодня попробовал скомпилировать там свой проект и сильно удивился увидев...

90
Наследование событий (events) в qt

Наследование событий (events) в qt

Есть главное окно QMainWindow

100
Вопрос по QProcess

Вопрос по QProcess

Мне нужно реализовать работу с терминалом из приложенияЗадача состоит в том что бы через ssh на сервер кидать проект,компилить его там,и возвращать...

161