Я занимаюсь разработкой двумерной космической игры для мобильных устройств, но она становится действительно сложной, и мое решение действительно сбивает с толку и производит много повторяющихся сегментов кода.
У меня есть мировой класс, в котором у меня есть несколько списков различных объектов, таких как:
List<Enemy> enemys;
List<Projectile> projectiles;
List<Collectable> collectables;
List<Asteroid> asteroids;
List<Effect> effects;
..
Каждый список обновляется мировым классом. но это еще не все .. У каждого врага есть список двигателей и список пусковых установок оружия, который обновляется противником. Теперь каждый движок добавляет некоторые эффекты огня в список «эффектов» мирового списка, а каждый пусковой механизм добавляет снаряды в список «снарядов» мирового списка. Все эти классы имеют разные параметры, поэтому мне нужно дополнительное обновление и дополнительная функция рендеринга для каждого класса.
По крайней мере, все они являются потомками GameObject, который предоставляет им базовые вещи, такие как векторы положения, скорости и ускорения, ограничивающие полигоны и функции, такие как applyForce и конечный автомат
Есть ли лучший или более распространенный способ сделать это? как один универсальный класс, который содержит все возможные параметры и методы для всех различных объектов. (я думаю, что это приведет к еще более запутанному коду)
источник
Ответы:
Да, это называется компонентной архитектурой. Посмотрите здесь для деталей.
Это позволило бы только один список сущностей в вашем мировом классе:
Это один из примеров композиции над наследованием .
источник
В рамках вашего исходного вопроса можно было бы разбить списки на Действия вместо Типов, как у вас. Например, у вас есть
List<HasAI>
и один для,List<Collidable>
и когда вы создаете новый объект, он добавляет себя в любой список действий, в котором он нуждается, когда объект уничтожается, он удаляет себя из этих списков. Объект может быть в нескольких списках.Второй шаг этого варианта заключается в преобразовании ваших классов из иерархии в иерархию, в которой используются интерфейсы, поэтому ваш тип HasAI - это класс, который в качестве примера реализует интерфейс IBrains. Соответствует
List<HasAI>
только тому, что объекты должны иметь интерфейс IBrains.Это должно помочь убрать некоторые сложности.
источник
Я думаю, что вам нужно сделать это абстрагирование рендеринга в свои классы, я думаю, один для игрока и один для врага (или, может быть, только один для игрока, а затем создать его экземпляр для игрока и врага - не уверен на 100% вашего игрового дизайна.)
Вы можете использовать шаблон посетителя, чтобы визуализировать цикл вокруг различных объектов и решить, что рисовать, что может быть менее сложным.
источник
Использование базового класса и использование полиморфизма - очень хорошая идея. Но есть несколько альтернативных подходов. Есть две статьи Ноэля Льописа, которые стоит прочитать. В последнее время я смотрю на Data Oriented Design и думаю, что в этом есть смысл.
Статьи здесь и здесь . Это может упростить ваш код немного больше, чем полиморфизм. Но, как и в случае с YMMV, посмотрите, соответствует ли это тому, чего вы пытаетесь достичь. Полиморфизм использует наследование, а DOD использует агрегацию, которая имеет свои плюсы и минусы, поэтому выбирайте яд.
источник
Вы можете использовать ООП и особенно полиморфизм.
По сути, вы должны создать базовый класс, от которого наследуются все игровые объекты. Этот базовый класс является настолько абстрактным, насколько это возможно, он будет содержать такие вещи, как функции создания, обновления и, возможно, уничтожения.
Затем вы получаете все остальные игровые объекты из этого класса. Возможно, вам также понадобится добавить какое-то отражение в ваш код, если ваш язык не поддерживает его, чтобы сделать более сложные вещи, но этого можно избежать, если вы знаете, как правильно структурировать наследование.
источник