Як я реалізую функції в системі сутності?


31

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

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


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

  • Сутність є ідентифікатором. У нього немає даних, це не об’єкт, це простий ідентифікатор, який представляє індекс у списку сцен усіх сутностей (який я насправді планую реалізувати як компонентну матрицю).

  • Компонент є власником даних, але з допомогою методів , які можуть працювати з цими даними. Найкращий приклад - Vector2Dкомпонент "Позиція". Він має дані: xі y, а також деякі методи , які роблять працюють на даних трохи простіше: add(), normalize()і так далі.

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


Камера

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

Як я міг представити такий тип об'єкта в системі сутності? Чи буде фотокамера сутністю, компонентом чи комбінацією (відповідно до моєї відповіді )?

Випромінювач частинок

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

Як я міг представити такий тип об'єкта в системі сутності?

Менеджер введення даних

Останнє, про яке я хочу поговорити, - це те, як слід обробляти дані. У моїй поточній версії двигуна є клас, який називається Input. Це обробник, який підписує події браузера, такі як натискання клавіш та зміни положення миші, а також підтримує внутрішній стан. Потім у класі гравця є react()метод, який приймає об’єкт введення як аргумент. Перевага цього полягає в тому, що об'єкт введення можна серіалізувати в .JSON, а потім поділитись по мережі, що дозволяє плавно проводити багатокористувацькі імітації.

Як це перекладається в систему сутності?

Відповіді:


26
  • Камера: Зробити цей компонент було б досить акуратно. Це було б простоisRenderingпрапор і дальність глибини, як сказав Шон. Окрім "поля зору" (я думаю, ви можете назвати це масштабом у 2D?) Та вихідної зони. Вихідна зона могла б визначити частину ігрового вікна, до якої ця камера потрапляє. У нього не було б окремого положення / обертання, як ви згадуєте. Суб'єкт, який ви створюєте, має компонент камери, використовує компоненти позиції та обертання цього об'єкта. Тоді у вас буде система камер, яка шукає об'єкти, які мають компоненти камери, положення та обертання. Система бере цю сутність і малює всі сутності, які вона може "бачити" з її положення, обертання, глибини зору та поля зору, до вказаної частини екрана. Це дає безліч варіантів моделювання декількох портів перегляду, вікон "перегляд символів", локальних мультиплеєрів,

  • Випромінювач частинок: Це теж повинно бути просто компонентом. Система частинок шукає сутності, які мають положення, обертання та випромінювач частинок. Емітер має всі властивості, необхідні для відтворення поточного випромінювача, я не впевнений, що це все, такі речі: швидкість, початкова швидкість, час розпаду тощо. Вам не доведеться робити кілька пропусків. Система частинок знає, які сутності мають цей компонент. Я думаю, ви могли б повторно використати значну частину наявного коду.

  • Вхідні дані: Я б сказав, що перетворення цього компонента має найбільш сенс, враховуючи вищезазначені пропозиції. Вашаinput systemбуде оновлюватися кожен кадр з поточними подіями введення. Тоді, коли він буде проходити всі сутності, які мають вхідний компонент, він застосує ці події. Компонент введення міститиме список подій клавіатури та миші, всі пов'язані з ними зворотні методи. Я не дуже впевнений, де житимуть методи зворотного виклику. Можливо, якийсь клас контролера на вході? Що б не мало сенсу для подальшої модифікації користувачами вашого двигуна. Але це дасть вам можливість легко застосовувати керування входом до об'єктів камери, об'єктів плеєра чи будь-чого, що вам потрібно. Хочете синхронізувати рух групи сутностей з клавіатурою? Просто дайте їм всі вхідні компоненти, які реагують на однакові входи, і система введення застосовує ці події переміщення до всіх компонентів, які просять їх.

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


Ще одна чудова відповідь! Спасибі! Тепер моя єдина проблема - це швидке зберігання та вилучення сутностей, тому користувач може реально реалізувати цикл гри / логіку ... Я спробую це розібратися самостійно, але спершу я повинен дізнатися, як Javascript справляється з масивами, об'єктами та невизначені значення в пам'яті, щоб добре здогадатися ... Це буде проблема, оскільки різні браузери можуть реалізувати це по-різному.
jcora

Це відчувається архітектурно чисто, але як система візуалізації визначає активну камеру за межі її повторення через усі об'єкти?
Темп

@Pace Оскільки я хотів би знайти активну камеру дуже швидко, я, швидше за все, дозволю системі камери зберігати посилання на сутності, які мають активну камеру.
MichaelHouse

Де ви вкладаєте логіку для керування кількома камерами (дивіться, обертайте, рухаєтесь тощо)? Як ви керуєте кількома камерами?
плазмацел

@plasmacel Якщо у вас є кілька об'єктів, які діляться елементами управління, ваша система управління буде відповідальна за визначення того, який об'єкт отримує входи.
MichaelHouse

13

Ось як я підійшов до цього:

Камера

Моя камера - це об'єкт, як і будь-який інший, який має вкладені компоненти:

  1. Transformмає Translation, Rotationі Scaleвластивості, на додаток до інших , для швидкості і т.д.

  2. Pov(Точка зору) має FieldOfView, AspectRatio, Near, Far, і все інше , потрібно , щоб зробити матрицю проекції, в доповненні до IsOrthoпрапору використовується для перемикання між перспективою і ортогональної проекцією. Povтакож надає ProjectionMatrixвластивість лінивого навантаження, що використовується системою візуалізації, яка внутрішньо обчислюється на зчитуванні та кешується, поки жодна з інших властивостей не буде змінена.

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

Вхідні дані

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

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

Ось обробник подій для обробки ключів, які утримуються між кадрами, які прикріплюються до InputReceiverкомпонента корабля (C #):

  void ship_input_Hold(object sender, InputEventArgs args)
    {
        var k = args.Keys;
        var e = args.Entity;

        var dt = (float)args.GameTime.ElapsedGameTime.TotalSeconds;

        var verlet = e.As<VerletMotion>();
        var transform = e.As<Transform>();

        if (verlet != null)
        {

        /// calculate applied force 
            var force = Vector3.Zero;
            var forward = transform.RotationMatrix.Up * Settings.ShipSpeedMax;

            if (k.Contains(Keys.W))
                force += forward;

            if (k.Contains(Keys.S))
                force -= forward;

            verlet.Force += force * dt;
        }

        if (transform != null)
        {
            var theta = Vector3.Zero;

            if (k.Contains(Keys.A))
                theta.Z += Settings.TurnRate;

            if (k.Contains(Keys.D))
                theta.Z -= Settings.TurnRate;

            transform.Rotation += theta * dt;
        }

        if (k.Contains(Keys.Space))
        {
            var time = (float)args.GameTime.TotalGameTime.TotalSeconds - _rapidFireLast;

            if (time >= _rapidFireDelay)
            {
                Fire();
                _rapidFireLast = (float)args.GameTime.TotalGameTime.TotalSeconds;
            }
        }
    }

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

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

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

Частинки

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

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

Тоді або у вашому MotionSystem(або в будь-якому іншому використанні, яке обробляє оновлення положення сутності тощо), або в спеціально ParticleSystemвиконаному будь-якій обробці, необхідній для кожної частинки на кадр. RenderSystemВідповідатиме за будівництво / дозування і кешування колекцій частинок , як вони створюються і знищуються, і роблять їх по мірі необхідності.

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

Висновок

Якщо ви плануєте перейти на платформу, що не стосується JavaScript, - весь ваш код платформи (а саме рендерінг та введення даних) виділений у дві системи. Ваша логіка гри залишається в платформо-агнозитних класах (рух, зіткнення тощо), тому вам не доведеться торкатися їх під час перенесення.

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


Де ви вкладаєте логіку для керування кількома камерами (дивіться, обертайте, рухаєтесь тощо)?
плазмацел

7

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

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

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


4

Камера буде сутністю чи просто компонентом?

Я не впевнений, що насправді задає це питання. Зважаючи на те, що у грі є лише сутності, то камери повинні бути сутностями. Функціональність камери реалізована за допомогою якогось компонента камери. Не майте окремих компонентів "Позиція" та "Поворот" - це занадто низький рівень. Вони повинні бути об'єднані в якийсь компонент WorldPosition, який би застосовувався до будь-якої організації, розташованої у світі. Щодо того, який з них використовувати ... ти повинен якось увійти в систему логікою. Або ви жорстко кодуєте його до системи обробки камери, або додаєте сценарії чи щось. Ви можете мати включений / вимкнений прапор на компоненті камери, якщо це допомагає.

Я впевнений, що самі частинки не повинні бути сутностями

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

Що стосується Input: введення не існує в світі ігор як такого, тому цим обробляє система. Не обов'язково «компонентну систему», оскільки не все у вашій грі обертається навколо компонентів. Але буде система введення. Можливо, ви хочете позначити суб'єкт, який реагує на вхід якоюсь складовою програвача, але вхід буде складним і цілком специфічним для ігор, тому мало намагатися робити компоненти для цього.


1

Ось кілька моїх ідей вирішення цих проблем. З ними, мабуть, буде щось не так, і, мабуть, буде кращий підхід, тому, будь ласка, направляйте мене до тих, хто у вашій відповіді!

Камера :

Є компонент "Камера", який можна додати до будь-якої сутності. Я не можу реально зрозуміти, які дані я повинен вносити в цей компонент, хоча: у мене могли бути окремі компоненти "Позиція" та "Поворот"! followМетод не повинен бути реалізований, тому що це вже наступний об'єкт він прикріплений до! І я вільний пересувати це. Проблемою з цією системою було б багато різних об’єктів камери: як можна RendererSystemзнати, які з них використовувати? А також, я просто передавав об'єкт камери навколо, але зараз, здається, RendererSystemпотрібно буде повторити два рази по всіх об'єктах : по-перше, щоб знайти тих, що діють як камери, і по-друге, щоб насправді зробити все.

ParticleEmitter :

Було б ParticleSystemоновити всі об'єкти, які мали компонент "Випромінювач". Частинки - це німі об'єкти у відносному координатному просторі, всередині цього компонента. Тут існує проблема візуалізації: мені потрібно або зробити ParticleRendererсистему, або розширити функціонал існуючої.

Система введення :

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


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

@ melak47, це правда, я про це теж думав, але хотів реалізувати це так, як це робить Ареміс. Але ця "система зберігання посилань на відповідні суб'єкти", здається, стає все більш і більш хибною ...
jcora

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