Обробка вводу в конструкції на основі компонентів


12

Мені відомо, що це запитання задавали кілька разів, але я все ще не впевнений, як реалізувати обробку вводу в двигуні на компонентній основі.

Використовуваний нами компонентний дизайн базувався на серіях блогів T = Machine і на Артеміді, в якій сутності - це лише ідентифікаційні дані.

Є три основні ідеї, які я маю щодо впровадження обробки даних:

  1. Вхідний компонент буде проводити події, які його цікавлять. Система введення буде переводити події ключів та миші на ігрові події та здійснювати циклічну передачу через об'єкти із вхідним компонентом, і якщо вони зацікавлені у події, система введення здійснить відповідні дії. Ця дія буде важко закодована для вхідної системи.
  2. Немає вхідного компонента. Ви б реєстрували об'єкти з певними подіями у системі вводу. Потім система введення надсилатиме повідомлення (з ідентифікатором сутності та типом події) іншим системам, щоб вони могли вжити відповідних дій. Або, як і в першому випадку, дії будуть жорстко кодовані до системи введення.
  3. Подібно до першого методу, але замість жорсткого кодування дії на вхідну систему компонент міститиме карту подій до функцій (тобто std::map<std::function>), які б викликалися системою введення. Це додає ефекту можливості з'єднати одну і ту ж подію з різними діями.

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

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


2
Зазвичай (коли камера стежить за плеєром), ви не хочете отримувати вхід в камеру, натомість ви змушуєте камеру перевіряти положення плеєра та слідувати за ним.
Лука Б.

1
Концептуально це не має значення, чи камера стежить за плеєром, чи "за собою". Тим не менш, я не впевнений, як Ваша пропозиція буде реалізована в дизайні на основі компонентів, не порушуючи принципів проектування.
Grieverheart

1
@Luke B .: Після того, як я подумав про це, я бачу, що ви також можете зробити камеру окремим класом, взявши вказівник на сутність, яку слід слідкувати.
Grieverheart

Відповіді:


8

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

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

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

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


Я грав на своє запитання деякою думкою і збирався відповісти на це сам. Я також дійшов висновку, що мені слід краще роз'єднати обробку вводу від системи ЕС, щоб було приємно бачити підтвердження цього. Як я думав це зробити, це через використання сигналів та можливість асоціювати кілька об'єктів до типу події. Я також вирішив роз’єднати камеру, хоча це насправді не потрібно, і мати це як сутність було б однаково життєздатним. Я думаю, що, будучи новачком з ЕК, ти справді повинен думати, які переваги може зробити щось складовою чи сутністю.
Grieverheart

4

Мій досвід може бути упередженим, але в декількох платформних проектах пристрої введення не піддаються безпосередньо системі сутності.

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

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

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

Потім ці генератори надсилають повідомлення / наміри для маршрутизації до системи намірів, де суб'єкти мають компонент або безпосередньо на потрібні компоненти.

Таким чином, ви можете просто покластися на те, що "завжди" має однаковий вхід, тобто JUMP_INTENT (1), JUMP_INTENT (0), AIM_INTENT (1) ...

І "всі" роботи, що залежать від брудної платформи, залишаються поза вашою системою сутності.


Що стосується камери, якщо ви хочете перемістити її по плеєру, вона може зареєструвати свій власний компонент наміру та прослухати наміри, які ви надішлете.

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


Койот, дякую за вашу відповідь. Крім того, я прочитав ваш інший пост тут . Моя найбільша стурбованість - це не те, як абстрагувати дані. У мене вже є конструкція нижчого рівня, яка обробляє натискання клавіш і таке інше, і додати ще один рівень непрямості не буде складно. Моя проблема полягає в обробці подій, створених, наприклад, вашою системою намірів. Якщо я правильно розумію, у вас немає вхідних компонентів у вашому методі. Звідки ви знаєте, яким суб'єктам потрібен вклад і як ви з ним працюєте? Чи можете ви навести кілька конкретніших прикладів?
Grieverheart

2

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

Action jump = () =>
{
    entities["player"].Transform.Velocity.Y += 5;
};

Інший приклад з ОП:

Action moveRight = () =>
{
    foreach (var entity in entities.Tagged("player", "camera"))
        entity.Transform.Position.X += 5;
};
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.