Наскільки об’єктно-орієнтованими є відеоігри? [зачинено]


18

Мені завжди було цікаво, якою мірою об'єктна орієнтація використовується відеоіграми, особливо величезними 3D-проектами. Я вважаю, що було б здорово, що обидва trollі werewolfуспадкували свої атрибути від enemyта перезаписали деякі з них. Але, можливо, заняття занадто важкі, щоб бути практичними, я не знаю ...


2
Як можна кількісно оцінити (або навіть об'єктивно кваліфікувати) орієнтацію на об'єкт? Ви хочете відповіді в Меєрі чи Далі-Нігаарді?

Очевидно, вони настільки важкі, що галузь, заснована на ОО, є галузевим стандартом.
Качка комуніста

4
Якщо ви маєте на увазі C ++, його вибрали, оскільки це гарна мова для вивчення загального для програмування універсального програмування з урахуванням швидкості; декілька функцій OOP, очевидно, прикрою помилкою, що зберігається лише для зворотної сумісності. ;)

Відповіді:


20

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

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

Розширення : у вашому прикладі Trollі Werewolfбуде розширюватися Enemy, що розширюється Entity. Entityпіклується про основні речі, такі як рух, здоров'я тощо, тоді як Enemyзаявлятиме про підкласи як ворогів та робить інші речі (Minecraft дотримується цього підходу).

На основі компонентів : Другий підхід (і мій улюблений) - це один Entityклас, у якому є компоненти. Компонентом може бути Moveableабо Enemy. Ці компоненти дбають про таке , як рух або фізика. Цей метод розбиває довгі ланцюги розширення і мінімізує ризик потрапляння в конфлікт. Наприклад: Як можна зробити ворогів, що не переміщуються, якщо вони успадковують від рухомого персонажа? .

У великих відеоіграх, таких як World of Warcraft або Starcraft 2, Entities - це не класи, а набори даних, які визначають цілу сутність. Сценарій також важливий, оскільки ви визначаєте, що Сутність не в класі, а в сценарії (якщо він унікальний, не такі речі, як переміщення).

В даний час я програмую RTS і використовую компонентний підхід з файлами Descriptor і Script для Entites, Skills, Items та всього іншого, що динамічно розвивається в грі.


2
Звучить інтерстинг. Однак я не брешу, я не знаю, що componentтаке в цьому контексті. Посилання буде дуже вдячним.
vemv

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

Компонент (іноді його називають системами Entity) - ви можете шукати в цьому блозі ідеї t-machine.org Є варіанти, але основна ідея полягає в тому, що компонент є об'єктом спеціального призначення і ваш актор пов’язує купу компонентів, як, наприклад, побудова моделі з Легоса.
Патрік Хьюз

2
Я започаткував блог про розробку ігор і написав свою першу запис у цьому блозі. Нічого нового, але з трохи коду: jagamedev.wordpress.com/2011/06/26/…
Марко,

23

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

На жаль, такий підхід до поліморфізму, популярний у 90-х, показав себе поганою ідеєю на практиці. Уявіть, що ви додаєте "вовка" до списку ворога - добре, він поділяє деякі атрибути з перевертнем, тому ви хочете об'єднати їх у спільний базовий клас, наприклад. 'WolfLike'. Тепер ви додаєте "Людину" до списку ворога, але перевертні іноді є людьми, тому вони також діляться атрибутами, наприклад, ходіння по 2 ногах, вміння розмовляти тощо. , і чи потрібно вам тоді зупинити перевертнів, що походять від WolfLike? Або ви примножуєте спадщину з обох - у такому випадку, який атрибут має перевагу, коли щось у Гуманоїді зіштовхується з чимось у WolfLike?

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

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

Але, можливо, заняття занадто важкі, щоб бути практичними, я не знаю ...

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


3
Люблю цю відповідь :)
Czarek Tomczak

8

Я не впевнений, що ви маєте на увазі під "надто важким", але C ++ / OOP - це лінгва-франка розвитку ігор з тих самих вагомих причин, що і в інших місцях.

Розмова про видувні кеші - це проблема дизайну, а не мовна особливість. C ++ не може бути занадто поганим, оскільки його використовували в іграх протягом останніх 15-20 років. Java не може бути надто поганим, оскільки використовується в дуже жорстких умовах роботи смартфонів.

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

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


2

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


Диспетчеризація серед різних поліморфних типів проводиться таким чином, що забезпечує погану локальність пам'яті. Навіть у найлегших вагових реалізаціях, таких як C ++ vtables або IM-кешування Objective-C, якщо ви насправді використовуєте поліморфізм для обробки об'єктів різного типу, ви будете дути свої кеші. Звичайно, якщо ви не використовуєте поліморфізм, ніж перебування vtable у вашому кеші, або повідомлення, кешоване IMP, веде до потрібного місця, але навіщо тоді турбуватися? А в Java або C # вартість важча, а в JavaScript або Python вартість все ж важча.

1
@Joe Wreschnig: Якщо ви використовуєте ці повільніші мови, то вартість ОО є тривіальною порівняно з іншими витратами, такими як переклад / JIT. Що ще важливіше, ви можете теоретично визначити, що ви хочете про погану локальність пам’яті, але факт полягає в тому, що передбачення гілок, виконання поза замовленнями і подібні функції в процесорі практично повністю знімають вартість. Інакше, чому так багато високоефективного програмного забезпечення пишеться з використанням об’єктної орієнтації?
DeadMG

1

Слід пам’ятати одне, що поняття об'єктно-орієнтованого коду часто є більш цінними, ніж їх реалізація в мовах. Зокрема, необхідність робити 1000 віртуальних викликів оновлень для осіб, що знаходяться в основному циклі, може спричинити безлад у кеші в C ++ на таких платформах, як 360 або PS3 - так що реалізація може уникнути "віртуальних" або навіть "класних" ключових слів заради швидкості.

Часто він все-таки буде слідувати поняттям OO про успадкування та інкапсуляцію - просто реалізуючи їх по-різному, як це робить мова (наприклад, цікаво рекурсивні шаблони, композиція замість успадкування (метод, заснований на компонентах, описаний Марко)). Якщо спадщину завжди можна вирішити під час компіляції, тоді проблеми з продуктивністю відходять, але код може стати трохи волохатим із шаблонами, спеціальними реалізаціями RTTI (знову ж таки, що вбудовані зазвичай не повільно повільні) або логіка часу компіляції у макроси і т.д.

У Objective-C для iOS / Mac є подібні, але ще гірші проблеми зі схемою обміну повідомленнями (навіть із фантазійними файлами кешування) ...


0

Метод, яким я буду намагатися використовувати спадкування класів сумішей та компонентів. (По-перше, я не роблю Enemy класом - я перетворюю його на компонент.) Мені не подобається ідея використання одного загального класу Entity для всього, а потім додавання необхідних компонентів для того, щоб вивести об'єкт із об'єкта. Натомість я вважаю за краще, щоб клас автоматично додавав компоненти (і значення за замовчуванням) в конструктор. Тоді підкласи додають свої додаткові компоненти в свій конструктор, тому підклас матиме його компоненти та компоненти його батьківського класу. Наприклад, клас Weapon додав би основні компоненти, спільні для всіх видів зброї, а потім підклас Sword додав би будь-які додаткові компоненти, характерні для мечів. Я все ще дискутую про те, чи потрібно використовувати текстові / xml-активи для визначення значень для сутностей (або конкретних мечів, наприклад), або робити це все в коді, або який правильний мікс. Це все ще дозволяє грі використовувати інформацію про тип кодової мови та поліморфізм, і робить ObjectFactories набагато простішим.


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