Найкращий спосіб керувати подіями в грі?


13

Я працюю над грою, де деякі події в грі повинні відбуватися раз у раз. Гарним прикладом може бути підручник. Ви починаєте гру, і в декількох моментах гри відбувається подія:

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

Гра, над якою я працюю, - це головоломка, де правила в грі майже однакові, тому важко кодувати всі ці події на окремих рівнях.

Чи варто якось визначити ці події у зовнішньому джерелі, як XML? Потім написати інтерпретатора, який зчитує XML і встановлює вимоги подій до рівня? Я не впевнений, як я міг би визначити подію, яка повинна статися, коли, наприклад, ти вбив двох ворогів.

Щоб було зрозуміло, я не шукаю найкращої мови програмування чи мови сценаріїв для цього, а більше - найкращого способу впоратися з цим.

Спасибі!


Редагувати: Другий приклад, оскільки моє запитання було досить важко зрозуміти:

Проблема, яка в мене виникає, полягає в тому, щоб вводити деякі зайві дії в гру в процедурі, яка завжди майже однакова. Як і у RPG битві, кожен має свою чергу, вибирає навички тощо - це завжди те саме. Але що робити, якщо трапився випадок, коли я хотів би показати десь між ними. Модифікування всієї ігрової структури для проходження в зміненому бойовому класі з включеним котценом здається дуже неефективним. Мені цікаво, як це зазвичай робиться.


8
Не намагайтеся надмірно узагальнити речі, наприклад, навчальні посібники дуже специфічні та мають багато різних тригерів / подій. Нічого поганого в жорсткому кодуванні / написанні сценаріїв.
Maik Semder

1
@Maik Якщо ви поставите це у відповіді Id +1 це .. Просте і вирішене краще, ніж будь-який день.
Джеймс

У вашому другому прикладі набагато зрозуміліше, що абстрактна система обміну повідомленнями буде великою виграшею. У підручнику ви можете просто важко зафіксувати речі, оскільки вони трапляються лише один раз на початку, але для поточних подій, які можуть статися в будь-який час протягом усієї тривалості гри, добре, що це інакше.
поштовх

Це все ще трохи розпливчасто, будь ласка, перелічіть щонайменше 3 тригери для 3 різних корців. взагалі дуже важко відповісти. В основному ви повинні знайти загальну схему, щоб зрозуміти, як її найкраще реалізувати.
Майк Семдер

Що ти хочеш? Ви хочете призупинити дії та зробити додаткові, а потім скасувати дії?
користувач712092

Відповіді:


7

Це дуже залежить від того, як насправді передаються події між об'єктами у вашій грі. Наприклад, якщо ви використовуєте центральну систему обміну повідомленнями, ви можете мати навчальний модуль, який прослуховує певні повідомлення та створює спливаючі вікна підручника кожного разу, коли він чує певні повідомлення. Тоді ви можете встановити, яке повідомлення для прослуховування, а також те, що з’являться для показу, у XML-файлі чи щось, що розбирається модулем підручника. Маючи окремий об’єкт підручника, який відстежує стан гри та відображає спливаючі віки підручника, коли він помічає речі в грі, ви можете змінювати об’єкт підручника за бажанням, не потребуючи нічого іншого про вашу гру. (Це візерунок спостерігача? Я не знайомий з усіма моделями дизайну.)

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


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

Ніколи не думав про щось на зразок спостерігача, це звучить як приємне рішення. Я спробую, дякую :)
omgnoseat

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. в "оновлення" ":
    • Ви просто перевіряєте потрібну подію натискання клавіш
    • Напевно вам потрібен масив / черга для проведення подій натискання клавіш
    • тоді Ви можете видалити його з черги дій та видалити об’єкт

Які методи навчитися


-1 правильно, або він просто викликає функцію, серйозно, ОП просто хоче, щоб поле вікна було виконано, коли певна умова виконана
Maik Semder

Thats дуже приємно написати, але не точно те, що я шукав. Мені було важко пояснити, що я хочу. Я додав друге пояснення: Проблема, яка у мене виникає, полягає в тому, щоб вводити додаткові дії в гру в процедурі, яка завжди майже однакова. Як і у RPG битві, кожен має свою чергу, вибирає навички тощо - це завжди те саме. Але що робити, якщо трапився випадок, коли я мав би показувати сцену десь посеред. Модифікування всієї ігрової структури для проходження у зміненому бойовому класі з включеним кроценом здається дуже неефективним. Мені цікаво, як це зазвичай робиться?
omgnoseat
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.