Стан гри та обробка вводу даних у компонентних системах сутності


16

Моє запитання:

Як я можу обробляти ігрові стани в моїй системі сутності, не вдаючись до збереження стопки об’єктів стану гри навколо?

Отже, дизайн моєї системи сутності означає, що коли суб'єкту потрібно зареєструватися, наприклад, для подій введення, компонент входу викликає систему введення та каже "зареєструвати цю сутність для цього вводу". Це все добре і добре, однак якщо додати до цього поняття ігрових станів (скажімо, екран пауз), це стане проблемою, щоб розробитись, якщо суб'єкт господарювання знаходиться у поточному стані і повинен отримати вхід.

Я міг би доповнити вхідний компонент / систему так, щоб він говорив, "зареєструйте цю сутність для цього вводу, перебуваючи в цих ігрових станах", але для цього потрібно, щоб кожен суб'єкт знав, у яких станах він буде використовуватися, і це може бути не очевидно. Крім того, зберігання списку ігрових станів навколо кожного зареєстрованого входу (та інших систем, що використовують зворотні дзвінки), не здається занадто ефективним.

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

Інша ідея полягає у тому, щоб усі системи зберігали свої дані, відведені до поточного стану, таким чином при генеруванні введення цільовий суб'єкт навіть не буде кандидатом. Однак це дійсно шкодить можливості дозволити спілкування між сутностями в різних станах (не стільки проблема для пауз екранів, але думка вибору блокування в Oblivion / Skyrim).

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

Другі (позначте об'єкт як відключений) і далі (кожен компонент має справу зі змінами стану) здаються найкращими з моїх ідей, але жодна з них не вискакує на мене як особливо велику.

Хтось ще має якісь ідеї, як це зробити?

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


6
Я це роблю так: у мене є екрани, MenuScreen PauseScreen GameScreen, кожен екран може створити свій власний світ (контейнер для сутностей) та системи (наприклад, RenderingSystem), а потім у GameScreen я створити World, Entity with CameraComponent і встановити CameraComponent.RenderTarget на екрани фону. Таким чином я можу додати InventoryScreen, який матиме власні сутності та системи (наприклад, спрощений візуалізатор). Введення даних може бути передано з екрана в світ, тому ваш інтерфейс користувача вирішить, чи буде він передавати вхід на екран (якщо його зосереджено, видно тощо), і чи буде він передавати дані світові та юридичним особам
Kikaimaru


2
@ Byte56 Насправді, лише перший стосується ігратів (інші 2 - це держави в межах об'єктів), і це насправді не вирішує ту саму проблему, що у мене. Коли гра знаходиться в призупиненому стані, з системою вводу має статися щось, щоб зупинити її надсилання повідомлень про рух гравцеві (наприклад), я просто не можу з’ясувати, як це зробити.
elFarto

1
Гаразд, вважайте їх пов’язаними тоді. Гарне питання.
MichaelHouse

1
Ще щось, що слід врахувати, що раніше було прикро для моїх компонентних систем: багатошаровий інтерфейс користувача. Діалогове вікно на вершині світових або багаторівневих екранів. До цих пір це доводилося в кожній грі, яку я робив, тому я б сказав, щоб обов'язково розглянути підхід, який може вирішити цю проблему.
ADB

Відповіді:


14

Те, що часто використовується, є проміжним Intent System який резюмує вхід і відстежує контекст та відповідні іграшки.

Система намірів припинить передавати входи, наприклад, коли моделювання призупинено. Він також обробляє відображення між подіями контролера та намірами (рухатися в напрямку, бігати, стріляти, перезавантажувати ...).

Таким чином, інші ваші компоненти не залежать від конкретних геймпадів / входів (BUTTON_A, BUTTON_B проти BUTTON_X, BUTTON_O ...), але всі вони реагують на однакові наміри (IntentRun, IntentReload ...).

Ще одна перевага полягає в тому, що система намірів може знати про наявні контролери, що додаються / видаляються, оскільки вона може надсилати наміри будь-якому абоненту, навіть поза імітацією, з якою можна обробляти такі наміри AddPlayer(controllerID).

Скільки інформації про стан гри ви надаєте системі або через події / повідомлення, або безпосередньо залежить від вас. Але час, вкладений у систему Намір, зазвичай того вартий.

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

Контекст може бути пріоритетним, тобто:

  • SimulaAvailableContext надсилає наміри до моделювання, поки воно доступне (але не працює), наприклад, перемістити камеру, збільшити масштаб, додати / видалити програвач ...
  • SimulaRunningContext надсилає наміри до імітації, поки це не призупинено рухати плеєр, відправити блок на позицію, стріляти ...

Таким чином ви можете додавати та видаляти контексти, які є актуальними на даний момент.

І одне про цілі системи намірів - це те, що вона повинна працювати під час призупинення моделювання.

Один із способів, який часто використовується для відтворення / паузи ігрового моделювання, не порушуючи оновлення, що не стосуються моделювання, - це використовувати різні набори разів. тобтоGenericSystem::onTime(Long time, Long deltaTime, Long simTime, Long simDeltaTime) .

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


Мені подобається те, що для цього не потрібно називати купу функцій "Змінено державою" для всіх об'єктів. Ви повинні турбуватися про те, що неправильні наміри надсилаються в неправильний час, але я думаю, що це краще, ніж альтернатива.
Томас Марнелл

ваші особи можуть ігнорувати такі наміри, як стрибок, поки їх стан не дозволяє стрибати (тобто не торкатися землі). але вони не повинні турбуватися про отримання таких намірів, поки гра призупинена.
Койот

Я вже думав про те, щоб дозволити суб’єкту повідомити системі введення, в яких станах надсилати повідомлення, але я не думав ставити штати на сам вхід, що є хорошою ідеєю. Також розділення часу та часу SimTime також приємно.
elFarto

Ви повинні уникати роздуття вашого стану, пов'язаного з імітацією, з речами, що не стосуються моделювання. Перемістіть увесь код інтерфейсу та плеєра якомога далі від самого моделювання та зосередьтеся лише на намірах.
Койот

Привіт @Coyote, ця система звучить дуже цікаво. Не могли б ви надати ще трохи інформації, відповідаючи на це запитання ? Спасибі!
пік

2

Як щодо створення глобальної системи подій, а потім скласти компонент слухача подій для кожної сутності? Після події "Зміна стану гри" ви можете поспілкуватися з компонентами індивідуально для кожного конкретного об'єкта.

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

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

Те, що я тільки що пояснив, є в основному практичним прикладом вашого четвертого рішення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.