Чому я повинен відокремлювати об'єкти від надання?


11

Відмова: Я знаю, що таке модель системи сутності, і я не використовую його.

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

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

Це не здається мені гарним рішенням. З іншого боку, дуже інтуїтивно уявити об'єкт як його 3d (або 2d) уявлення, а також дуже простий у обслуговуванні (і, можливо, набагато більш інкапсульований також).

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

(можливо, із прикладами, я не дуже добре розумію абстрактні розмови)


1
Було б також корисно, якщо ви надасте приклад того, що ви маєте на увазі, коли ви говорите, що не використовуєте системний зразок сутності, і як ви думаєте, що це стосується того, чи слід відокремлювати питання про надання, від турботи суб'єкта господарювання / логіка гри.
michael.bartnett

@ michael.bartnett, я не розділяю об'єкти на невеликі багаторазові компоненти, якими обробляються системи, як це робить більшість реалізацій шаблонів. Мій код - це скоріше спроба схеми MVC. Але це насправді не має значення, оскільки питання не залежить від будь-якого коду (навіть мови). Я поставив заяву, що знав, що деякі намагаються переконати мене в застосуванні ЕКС, що, здається, вилікує рак. І, як бачите, це все одно сталося.
взуття

Відповіді:


13

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

Тож ваша сцена виглядає приблизно так:

class Scene {
    World* world
    Player* player
    Enemy* boss
    Camera* camera
}

(Принаймні, це основні дані . Ви вирішуєте, яким чином ви містять дані.)

Ви хочете оновити та відредагувати сцену лише тоді, коли ви граєте в гру, а не під час пауз чи в головному меню ... тому ви приєднаєте її до ігрового стану!

State* gameState = new State();
gameState->addScene(scene);

Тепер у вашому ігровому стані є сцена. Далі потрібно запустити логіку на сцені та вивести на сцену. Для логіки ви просто запускаєте функцію оновлення.

State::update(double delta) {
    scene->update(delta);
}

Таким чином ви зможете зберегти всю логіку гри в Sceneкласі. І лише задля посилання, система компонент сутності може зробити це так:

State::update(double delta) {
    physicsSystem->applyPhysics(scene);
}

У будь-якому випадку, вам зараз вдалося оновити свою сцену. Тепер ви хочете його відобразити! Для чого ми робимо щось подібне до вищезгаданого:

State::render() {
    renderSystem->render(scene);
}

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

RenderSystem::renderScene(Scene* scene) {
    Camera* camera = scene->camera;
    lookAt(camera); // Set up the appropriate viewing matrices based on 
                    // the camera location and direction

    renderHeightmap(scene->getWorld()->getHeightMap()); // Just as an example, you might
                                                        // use a height map as your world
                                                        // representation.
    renderModel(scene->getPlayer()->getType()); // getType() will return, for example "orc"
                                                // or "human"

    renderModel(scene->getBoss()->getType());
}

Дійсно спрощеним, вам все-таки потрібно буде, наприклад, застосувати обертання та переклад залежно від того, де знаходиться ваш плеєр та де він шукає. (Мій приклад - 3D-гра; якщо ви їдете з 2D, це буде прогулянка по парку).

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

І вам також не потрібно прикріплювати інформацію про надання на сцені. Повинно бути достатньо, щоб рендер знав, що йому потрібно видати орка. Ви вже завантажили модель орків, яку рендер тоді знає відображати.

Це повинно відповідати вашим вимогам. Графічне зображення та логіка поєднані , оскільки вони обидва використовують однакові дані. І все ж вони є окремими , бо ні на кого не покладається!

EDIT: І просто відповісти, чому хтось зробив би це так? Тому що це легше - це найпростіша причина. Вам не потрібно думати про "таке і таке сталося, я зараз повинен оновлювати графіку". Натомість ви робите речі, і кожен кадр гри дивиться на те, що зараз відбувається, і певним чином інтерпретує це, даючи на екрані результат.


7

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

Друге питання було розглянуто раніше , тому я зупинюсь на першому питанні.

Причини розмежування логіки та візуалізації:

  1. Поширене уявлення про те, що об’єкти повинні робити одне
  2. Що робити, якщо ви хочете перейти від 2D до 3D? Що робити, якщо ви вирішите перейти від однієї системи візуалізації до іншої в середині проекту? Ви не хочете проскакувати весь код і внести величезні зміни в середину логіки гри.
  3. Ви, ймовірно, матимете підстави повторити розділи коду, що, як правило, розцінюється як погана ідея.
  4. Ви можете побудувати системи для управління потенційно величезними ділянками візуалізації або логіки без індивідуального спілкування з невеликими шматочками.
  5. Що робити, якщо ви хочете призначити дорогоцінний камінь гравцеві, але система сповільнюється на скільки граней має дорогоцінний камінь? Якщо ви досить добре абстрагували систему візуалізації, ви можете її оновлювати різними тарифами, щоб врахувати дорогі операції візуалізації.
  6. Це дозволяє думати про речі, які дійсно мають значення для того, що ти робиш. Навіщо обмотати мозок навколо матричних перетворень та спрацьовувати зміщення та координати екрану, коли все, що ви хочете зробити, це здійснити механіку подвійного стрибка, намалювати карту чи оснастити меч? Ви не хочете, щоб спрайт, що представляє ваш обладнаний меч, передавав яскраво-рожевий колір лише тому, що ви хотіли перемістити його з правої руки на ліву.

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


6

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

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

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

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

введіть тут опис зображення

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

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

В іншому випадку природним способом впоратися з таким випадком є ​​проектування системи як введення / виводу. Оновлення виконує логіку та виводить результат. Відображення подається лише з результатами оновлення. Вам не потрібно все викривати. Ви виставляєте лише інтерфейс, який спілкується між двома етапами. Зв'язок між різними частинами двигуна повинен здійснюватися за допомогою абстракцій (інтерфейсів) та / або повідомлень. Жодна внутрішня логіка чи стани не повинні піддаватися впливу.

Візьмемо простий приклад графічного сюжету для пояснення ідеї.

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

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

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