Лучший способ управлять внутриигровыми событиями?

13

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

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

Игра, над которой я работаю, - это игра-головоломка, в которой правила игры почти одинаковы, поэтому неэффективно жестко кодировать все эти события на разных уровнях.

Должен ли я как-то определить эти события во внешнем источнике, таком как XML? Затем напишите интерпретатор, который считывает XML и устанавливает требования к событиям для уровня? Я не уверен, как я мог определить событие, которое должно произойти, когда вы убили двух врагов, например.

Просто чтобы быть ясным, я не ищу лучший язык программирования или язык сценариев для этого, но больше лучший способ справиться с этим.

Благодарность!


Изменить: второй пример, так как мой вопрос было довольно трудно понять:

Проблема, которую я имею, состоит в том, чтобы добавить в игру некоторые дополнительные действия, которые всегда одинаковы. Как и в RPG-битве, у каждого есть свой ход, он выбирает навык и т. Д. - он всегда один и тот же. Но что, если бы был случай, когда я хотел бы показать кат-сцену где-то посередине. Modyfing всю структуру игры, чтобы пройти в измененном боевом классе с включенной заставкой, кажется очень неэффективным. Мне интересно, как это обычно делается.

omgnoseat
источник
8
Не пытайтесь чрезмерно обобщать вещи, учебники, например, очень специфичны и содержат много разных триггеров / событий. Ничего плохого в жестком кодировании / написании сценариев.
Майк Земдер
1
@Maik Если вы включите это в ответ Id +1 это .. Простой и решаемый лучше, чем в любой прекрасный день.
Джеймс
Ваш второй пример проясняет, что абстрактная система обмена сообщениями была бы большой победой. Для учебника вы можете просто жестко закодировать вещи, так как они происходят только один раз в самом начале, но для текущих событий, которые могут произойти в любое время на протяжении всей игры, все по-другому.
Джокинг
Это все еще немного расплывчато, пожалуйста, перечислите по крайней мере 3 триггера для 3 различных кат-сцен. в общем, очень сложно ответить. По сути, вы должны найти общий шаблон, чтобы понять, как его лучше всего реализовать.
Майк Земдер
Чего ты хочешь? Вы хотите приостановить действия и выполнить дополнительные действия, а затем приостановить действия?
user712092

Ответы:

7

Это во многом зависит от того, как события фактически передаются между объектами в вашей игре. Например, если вы используете центральную систему обмена сообщениями, то у вас может быть учебный модуль, который прослушивает определенные сообщения и создает всплывающие окна учебника всякий раз, когда он слышит определенные сообщения. Затем вы можете указать, какое сообщение прослушивать, а также какое всплывающее окно показывать, в файле XML или в том, что анализируется учебным модулем. Имея отдельный учебный объект, который отслеживает состояние игры и отображает всплывающие подсказки, когда он замечает какие-либо вещи в игре, вы можете изменить учебный объект по своему усмотрению, не внося никаких изменений в свою игру. (Это шаблон Observer? Я не знаком со всеми шаблонами проектирования.)

В целом, хотя это зависит от сложности вашего урока, стоит ли беспокоиться об этом. Жесткое кодирование событий в вашем коде и / или уровнях не кажется для меня большой проблемой для всего лишь нескольких всплывающих окон. Мне любопытно, что именно вы имеете в виду, что заставляет вас думать, что это будет неэффективно, поскольку все, что вы должны делать при каждом запуске, - это просто отправлять сообщение в учебный модуль, что-то вроде TutorialModule.show ("1st_kill");

jhocking
источник
Я думаю, что так как это игра-головоломка, его логика в одном месте для нескольких уровней и тому подобное, делая проверки, если мы сделаем учебник для этого, что-то, что длится во всем. Честно говоря, если это игра-головоломка, я не думаю, что она получит огромный успех, даже если это не самый красивый код, и в конце дня код, который работает в игре, которая всегда есть, всегда-всегда- 100% лучше, чем красивый код, который никогда не увидит свет;)
Джеймс
Никогда не думал о чем-то вроде схемы наблюдателя, звучит как хорошее решение.
Я
7

Вот ограничения дизайна, как я их понимаю:

  1. Основной код игрового процесса не заботится о требованиях к уровню и не должен быть связан с кодом, который им занимается.

  2. В то же время, это основной код игрового процесса, который знает, когда происходят конкретные события, отвечающие этим требованиям (получение предмета, убийство врага и т. Д.)

  3. Различные уровни имеют разные наборы требований, и их нужно где-то описать.

Учитывая это, я бы, вероятно, сделал что-то вроде этого: во-первых, создайте класс, который представляет игровой уровень. Он будет включать в себя набор конкретных требований, предъявляемых к уровню. У него есть методы, которые можно вызывать, когда происходят игровые события.

Дайте ядру игрового кода ссылку на объект текущего уровня. Когда происходит событие геймплея, он расскажет уровень, вызывая его методу: enemyKilled, itemPickedUpи т.д.

Внутренне Levelнужно несколько вещей:

  • Состояние, чтобы отслеживать, какие события уже произошли. Таким образом, он может отличить первого убитого врага от других, и знает, когда вы впервые взяли данный предмет.
  • Список LevelRequirementобъектов, которые описывают определенный набор целей, которые вам нужны для этого уровня.

Когда вы входите в уровень, вы создаете Levelправильные LevelRequirements, настраиваете код игры и задаете ему этот уровень.

Каждый раз, когда происходит игровое событие, игровой процесс передает его Level. Это, в свою очередь, вычисляет совокупные данные (общее количество убитых врагов, убитых врагов этого типа и т. Д.). Затем он просматривает свои объекты требований, предоставляя каждому агрегированные данные. Требование проверяет, выполнено ли оно, и если да, то порождает любое подходящее поведение в результате (показ учебного текста и т. Д.)

LevelRequirement в основном нужны две вещи:

  1. Описание теста, чтобы сказать, было ли выполнено требование. Это может быть просто функция, если ваш язык облегчает эту задачу, в противном случае вы можете смоделировать ее в данных. (То есть есть RequirementTypeперечисление с такими вещами, как, FIRST_KILLа затем большой, switchкоторый знает, как проверить каждый вид.)
  2. Действие, которое нужно выполнить, когда требование выполнено.

Остается вопрос, где описаны эти наборы требований? Вы можете сделать что-то вроде XML или другой формат текстового файла. Это полезно, если:

  1. Непрограммисты будут создавать уровни.
  2. Вы хотите иметь возможность изменять требования без перекомпиляции и / или перезапуска.

Если ни один из этих случаев не подходит, я бы, вероятно, просто сконструировал их непосредственно в коде. Проще всегда лучше.

необычайно щедрый
источник
Первые 3 пункта - очень точное описание метода, который я использую сейчас, впечатляет! Да, с чем я больше всего борюсь, так это с тем, где описать требование и как перевести его в игру (поскольку, скорее всего, это будет нечто внешнее). Спасибо за подробное объяснение :)
omgnoseat
5

Я подумал, что Вам нужно знать, как сделать эти события, а остальная часть поста об этом. Если вы хотите просто сохранить эти события, то используйте некоторую реляционную базу данных или опишите их с помощью текста и используйте язык сценариев (он выполнит анализ и оценку для Вы). :)

Вам нужно распознать произошедшие события (1), а затем выполнить некоторые действия, которые требуются этими событиями (распечатать сообщение, проверить нажатие клавиши ...) (2). Вы также хотите, чтобы эти события происходили только один раз (3).

По сути, вы хотите проверить условия, а затем запланировать некоторые действия.

Как распознать события (1)

  • Вы хотите распознать такие события, как «встретившийся первый враг», «приобретенный новый предмет»
  • если происходит общая часть, « обнаружен враг », « предмет получен », вы проверяете конкретную часть « первым ...», « получен новый предмет»

Из чего сделаны события

В более общем виде каждое такое событие состоит из:

  • предпосылки , вы их проверяете
  • действия, которые будут выполнены, когда будут выполнены предварительные условия (скажем, «Вы убили первого врага!», произнесите «сделать комбо нажатием кнопок A и B», произнесите «нажмите Enter» для продолжения », нажмите клавишу« enter »)

Как хранить эти события

В некоторой структуре данных:

  • иметь список предварительных условий (строки или код, если Вы пишете это на каком-либо языке высокого уровня)
  • иметь список действий (это могут быть строки, движок Quake использует строки для событий)

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

Затем вы должны разобрать эти строки / вещи. Или Вы можете использовать некоторый язык сценариев, такой как Python или LUA, или язык, такой как LISP, они все могут проанализировать и выполнить его для Вас. :)

Как использовать эти события в игровом цикле (2)

Вам понадобятся эти две структуры данных:

  • очередь событий (события, которые запланированы для запуска, помещены здесь)
  • очередь действий (запланированные действия, события подразумевают, какие действия выполнены)

Алгоритм:

  • Если Вы признаете некоторые события «s предпосылки будут выполнены Вы кладете его в очередь событий
  • (3) Тогда Вы должны убедиться, что это событие произошло только один раз, если Вы хотите :) (например, с логическим массивом has_this_event_happened ["первый враг встретился"])
  • (если очередь действий пуста, то) Если в очереди событий есть событие, вы помещаете его действия в очередь действий и удаляете его из очереди событий.
  • Если в очереди действий есть действие, вы начинаете делать то, что от него требуется
  • Если такое действие выполнено, Вы удаляете его из очереди действий.

Как сделать эти действия самостоятельно (2)

Вы составляете список объектов, у которых есть функция «обновление». Их иногда называют сущностями (в движке Quake) или актерами (в движке Unreal).

  1. Вы запускаете эти объекты, когда они требуются для запуска в очереди действий.
  2. эти объекты могут быть использованы для других вещей, таких как некоторые другие таймеры. В Quake эти объекты используются для всей игровой логики, я рекомендую вам прочитать некоторые материалы об этом .

Акция "скажи что-нибудь"

  1. Вы печатаете что-то на экране
  2. Вы хотите, чтобы это сообщение появилось на несколько секунд
  3. в "обновлении":
    • сделать переменную remove_me_after и уменьшить ее на время, которое прошло
    • когда переменная равна 0 Вы удаляете это действие из очереди действий
    • Вы также удаляете этот объект (или планируете его удалить ...)

Действие "Требуется ключ"

  1. Это зависит от того, как вы хотите это сделать, но я думаю, что вы делаете сообщение
  2. в "обновлении" ":
    • Вы просто проверяете желаемое событие нажатия клавиши
    • Возможно, вам нужен массив / очередь для хранения событий нажатия клавиш
    • Затем Вы можете удалить его из очереди действий и удалить объект

Какие методы выучить

user712092
источник
-1 верно, или он просто вызывает функцию, серьезно, OP просто хочет окно сообщения, когда определенное условие выполнено
Maik Semder
Это очень хорошая запись, но не совсем то, что я искал. Мне было трудно объяснить, чего я хочу. Я добавил второе объяснение: проблема, которую я имею, состоит в том, чтобы добавить некоторые дополнительные действия в игру в процедуру, которая всегда почти одинакова. Как и в RPG-битве, у каждого есть свой ход, он выбирает навык и т. Д. - он всегда один и тот же. Но что, если бы был случай, когда я должен был показать сцену где-то посередине. Modyfing всю структуру игры, чтобы пройти в измененном боевом классе с включенным cutsene, кажется очень неэффективным. Мне интересно, как это обычно делается?
omgnoseat