Я неопытный программист, создающий "похожую на roguelike" игру в духе FTL с использованием Python (пока PyGame нет, так как я до сих пор занимаюсь только текстом).
Моя игра будет содержать большое количество оружия (около 50 для начинающих), дающего уникальные способности. Я изо всех сил пытаюсь понять, как структурировать объектный код таким образом, чтобы он был мощным (с точки зрения предоставления оружию радикально отличающихся эффектов) и расширяемым (чтобы я мог легко добавить больше оружия позже, например, поместив его в папку ).
Моим первым инстинктом было иметь класс BasicWeapon и иметь другое оружие, унаследованное от этого класса. Тем не менее, это кажется мне проблематичным: либо я должен сделать класс BasicWeapon настолько скромным, что он в принципе бесполезен (единственными функциями, которые имеют все оружие, являются имя и тип (пистолет, топор и т. Д.)), Либо я должен предсказать каждый уникальный эффект, который я когда-либо придумаю и закодирую в BasicWeapon.
Последнее явно невозможно, но с первым все еще можно работать. Однако, это оставляет меня с вопросом: куда я могу поместить код для индивидуального оружия?
Должен ли я создать plasmarifle.py, rocketlauncher.py, swarmofbees.py и т. Д. И т. Д. И поместить их в папку, откуда игра может их импортировать?
Или есть способ иметь файл в стиле базы данных (может быть, такой простой, как электронная таблица Excel), который каким-то образом содержит уникальный код для каждого оружия - без необходимости прибегать к eval / exec?
Что касается последнего решения (базы данных), я думаю, что основная проблема, с которой я борюсь, заключается в том, что, хотя я понимаю, что желательно поддерживать разделение между кодом и данными, я чувствую, что оружие стирает грань между «кодом» и немного "данных"; они представляют большое разнообразие похожих вещей, которые можно найти в игре, в этом смысле они похожи на данные, но большинству из них потребуется, по крайней мере, какой-то уникальный код, не предоставленный другим элементам, в каком смысле они, естественно, код.
Частичное решение, которое я нашел в другом месте на этом сайте, предлагает дать классу BasicWeapon набор пустых методов - on_round_start (), on_attack (), on_move () и т. Д., А затем переопределить эти методы для каждого оружия. На соответствующей фазе боевого цикла игра будет вызывать соответствующий метод для оружия каждого персонажа, и только те, у которых есть определенные методы, будут действительно что-то делать. Это помогает, но это все еще не говорит мне, где я должен поместить код и / или данные для каждого оружия.
Есть ли другой язык или инструмент, который я мог бы использовать как своего рода половину данных, половину кода? Я полностью оправдываю хорошую практику программирования?
Мое понимание ООП в лучшем случае схематично, поэтому я был бы признателен за ответы, которые не слишком информатичны.
РЕДАКТИРОВАТЬ: Vaughan Hilts ясно дал понять в своем посте ниже, что я по сути говорю о программировании на основе данных. Суть моего вопроса заключается в следующем: как я могу реализовать управляемый данными дизайн таким образом, чтобы данные могли содержать сценарии, позволяющие новому оружию делать новые вещи, не меняя основной программный код?
источник
Ответы:
Вы почти наверняка нуждаетесь в подходе, основанном на данных, если ваша игра не будет совершенно неожиданной и / или процедурной, сгенерированной до глубины души.
По сути, это включает в себя хранение информации о вашем оружии на языке разметки или формате файла по вашему выбору. XML и JSON являются хорошими читаемыми вариантами, которые можно использовать для упрощения редактирования без необходимости в сложных редакторах, если вы просто пытаетесь получить быстрый старт. ( И Python также может анализировать XML довольно легко! ) Вы бы установили такие атрибуты, как «сила», «защита», «стоимость» и «статистика», которые все имеют отношение. То, как вы структурируете свои данные, будет зависеть от вас.
Если оружию нужно добавить эффект статуса, назначьте ему узел эффекта статуса, а затем укажите эффекты эффекта статуса через другой объект, управляемый данными. Это сделает ваш код менее зависимым от конкретной игры и сделает редактирование и тестирование вашей игры тривиальным. Не нужно перекомпилировать все время, это тоже бонус.
Дополнительное чтение доступно ниже:
источник
(Извините, что отправляю ответ вместо комментария, но у меня пока нет представителя.)
Ответ Вогана великолепен, но я бы хотел добавить свои два цента.
Одна из основных причин, по которой вы хотите использовать XML или JSON и анализировать их во время выполнения, - это изменение и экспериментирование с новыми значениями без перекомпиляции кода. Поскольку Python интерпретируется и, на мой взгляд, довольно читабелен, вы можете хранить необработанные данные в файле со словарем и всем организованным:
Таким образом, вы просто импортируете файл / модуль и используете его как обычный словарь.
Если вы хотите добавить сценарии, вы можете использовать динамическую природу функций Python и 1-го класса. Вы могли бы сделать что-то вроде этого:
Хотя я считаю, что это будет против дизайна, управляемого данными. Чтобы быть на 100% DDD, у вас будет информация (данные), определяющая, какие функции и код будет использоваться конкретным оружием. Таким образом, вы не нарушаете DDD, поскольку не смешиваете данные с функциональностью.
источник
Управляемый данными дизайн
Я отправил что-то вроде этого вопроса в обзор кода недавно.
После некоторых предложений и улучшений, результатом стал простой код, который позволял бы относительную гибкость при создании оружия на основе словаря (или JSON). Данные интерпретируются во время выполнения, и
Weapon
сам класс выполняет простые проверки без необходимости полагаться на весь интерпретатор сценариев.Проектирование на основе данных, несмотря на то, что Python является интерпретируемым языком (исходные файлы и файлы данных могут редактироваться без необходимости их перекомпиляции), звучит как правильное решение в таких случаях, как тот, который вы представили. Этот вопрос более подробно раскрывает концепцию, ее плюсы и минусы. Theres также хорошая презентация в Корнельском университете об этом.
По сравнению с другими языками, такими как C ++, которые, вероятно, будут использовать язык сценариев (например, LUA) для обработки взаимодействия с механизмом данных и сценариями в целом, а также определенный формат данных (например, XML) для хранения данных, Python действительно может сделать все самостоятельно его ( с учетом стандарта ,
dict
но иweakref
, в частности , последний для загрузки ресурсов и кэширования).Независимый разработчик, однако, не может использовать управляемый данными подход до предела, как предлагается в этой статье :
Возможно, с Python можно было бы извлечь выгоду из лучшего как объектно-ориентированного, так и управляемого данными подхода, нацеленного как на производительность, так и на расширяемость.
Простая обработка образцов
В конкретном случае, обсуждаемом при проверке кода, словарь будет хранить как «статические атрибуты», так и логику, которую нужно интерпретировать - если оружие будет иметь какое-либо условное поведение.
В приведенном ниже примере меч должен иметь некоторые способности и характеристики в руках персонажей класса «антипаладин», и никаких эффектов, с более низкими характеристиками при использовании другими персонажами):
Для целей тестирования я создал простые
Player
иWeapon
классы: первый для хранения / оснащения оружия (таким образом вызывая его условную настройку on_equip), а второй - как отдельный класс, который будет извлекать данные из словаря на основе имени элемента, переданного как аргумент во времяWeapon
инициализации. Они не отражают правильное оформление игровых классов, но все же могут быть полезны для проверки данных:С некоторыми будущими улучшениями я надеюсь, что это позволит мне когда-нибудь иметь динамическую систему крафта, обрабатывая компоненты оружия вместо целого оружия ...
Тест
Так:
Следует напечатать:
Для барда
Для антипаладина
источник