Як зробити гру без OOP? [зачинено]


10

Я зараз вивчаю розробку ігор та практикую створення ігор.

Я використовую багато OOP у своїх іграх. Наприклад, кожна вистрілена ракета є екземпляром Missileоб'єкта і додається до списку Missileоб'єктів. Кожен танк у грі - Tankпредмет. І т.д.

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

Мені важко уявити, як гра (яка є більш складною, ніж Pac-Man) могла бути запрограмована мовою, що не є OO. (Звичайно, без поваги до програмістів, що не входять в ООС). Не лише з точки зору того, як триватиме це, але, здебільшого, з точки зору того, як гра могла бути задумана таким чином.

Я не уявляю, як створити гру без використання об'єктно-орієнтованого програмування, оскільки все моє розуміння того, як створити ігрову програму, базується на OOP.

Я хотів би запитати: чи існують сьогодні ігри, які не запрограмовані за допомогою OOP, подібним чином до того, що я описав вище? Чи є якісь «професіональні» ігри, які не використовують OOP як головний фактор у процесі розвитку?

Якщо так, чи можете ви дати мені уявлення про те, як, наприклад, можна виявити зіткнення між танком і N кількістю ракет без OOP?


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

У багатьох іграх використовується система на основі компонентів, як ця відповідь описує: gamedev.stackexchange.com/a/31491/9366
Джон Макдональд,

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

Це може бути придатним для StackOverflow, або ви можете переглянути довідковий центр, щоб знайти підбірку сайтів, специфічних для ігрових розробок (наприклад, GDNet), які дозволили б отримати таку широку тему, орієнтовану на обговорення. Удачі!

Відповіді:


16

Я не уявляю, як створити гру без використання об'єктно-орієнтованого програмування, оскільки все моє розуміння того, як створити ігрову програму, базується на OOP.

Тоді вам, мабуть, буде добре спробувати написати деякі програми в стилі, що не входить в ООС. Навіть якщо ви виявите, що це для вас не прагматично, ви, ймовірно, багато чого навчитеся на цьому шляху, що допоможе вам у майбутньому.

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

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

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

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

У цій серії статей у блозі є більше думок щодо написання ігор у функціональному стилі:

http://prog21.dadgum.com/23.html

Ця стаття спеціально стосується вашого питання "снаряд потрапляє в танк":

http://prog21.dadgum.com/189.html

Насправді просто прочитайте весь блог. Там хороші речі, а статті короткі.


12

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

Тому

 missile.setVelocity(100);

стає

 setMissileVelocity(missile, 100);

або коли ця функція тривіальна, ви просто виконуєте

 missile.velocity = 100;

Основна відмінність об'єктно-орієнтованого програмування від процедурного програмування полягає в тому, як ви ставитеся до своїх даних. В OOP дані розумні . Він управляє і маніпулює собою. Але в процедурному програмуванні дані німі . Він нічого не робить самостійно і ним потрібно маніпулювати ззовні.

Якщо ви навіть вважаєте структури занадто об'єктно-орієнтованими, ви можете замінити один масив структур декількома масивами, один на все, що було б змінною ракети. Тому

struct Missile {
     int x;
     int y;
     int velocity;
}

Missile missiles[256];

стає

int missileX[256];
int missileY[256];
int missileVelocities[256];

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

function updateMissilePosition(int index) {
     missileX[index] += missileVelocity[index];
}

1
Але missileце екземпляр об'єкта. У не-OOP немає випадків, я прав? Якщо так, як ви могли встановитиMissileVelocity (ракета, 100)?
користувач3150201

1
@ user3150201 Ви не зовсім правильні. Більшість мов, що не належать до OOP (і я б заперечував майже будь-яку, що підходить для серйозних ігор) розробляє структури. Структура схожа на клас, тільки що вона не містить нічого, крім загальнодоступних змінних. Так що це дозволить вам створити тип Missile, який представляє собою структуру з декількома полями, як x, y, angleі velocity.
Філіп

@ user3150201 Оновлена ​​відповідь з розділом про те, як це зробити без структур.
Філіп

Приємна відповідь Філіп, хоча я не розумію, чому б хто не хотів програмувати об'єктно-орієнтовані. Читати мови, які не є OOP, насправді важко, і це може викликати роздратування. Код може заплутатися в найкоротші терміни.
Джафур

2
@Zhafur Ви знаєте, що ваша заява є масовим вогнем, чи не так?
Філіп

6

Я роблю це так:

  • Усі класи / методи OOP мають доступ до this. Для того, щоб використовувати thisв підході, що не є ООС, просто перейдіть у будь-який екземпляр (див. Наступний пункт) this, як перший параметр.
  • Тепер, що стосується екземплярів, ви можете передавати structs у свої функції як this, але я вважаю, що найкращий спосіб досягти хорошої продуктивності кешу для об'єктів, які є плодовитими, наприклад, сутностей або частинок, - це просто передати один індекс у кілька масивів примітивів або малі structs. Отже цей індекс використовується для кожного окремого члена даних початкового класу. Так, наприклад, якщо у вас був

...

class Entity //let's say you had 100 instances of this
{
   int a;
   char b;
   function foo() 
   {
      .../*can access 'this' herein*/
   }
}

Ви замінили б це

int a[100];
char b[100];
function foo(int index);

Отже, ви зараз передаєте індекс у функцію, щоб отримати те, що зазвичай було б this.

Майте на увазі, що ви можете використовувати або масиви примітивів, як зазначено вище, або масиви structs, залежно від того, як найкраще переплетені ваші дані для гарної локальності кешу (місцеположення). Звичайно, пристойна кеш-ефективність покладається на набагато більше, ніж це - особливо, на якій мові / платформі ви пишете свій код - але навіть у VM-основі, динамічно розподілених мовах, таких як Java, великі лінійні масиви примітивів, як правило, відображати кращі характеристики продуктивності, ніж об’єкти об'єкта. Основна причина цього полягає в тому, що до об'єктів звертаються за посиланням, а це означає, що ви перестрибуєте всю пам'ять, щоб отримати доступ до даних - неефективний порівняно з доступом до примітивів безперервно з великого масиву.

Для отримання додаткової інформації про створення будівельних об'єктів тощо як масиву конструкцій чи примітивів див. Статтю Mick West's Evolve your Iierarchy .


0

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

Є два підходи:

Збереження типу

У цьому випадку в структурі є поле для ідентифікатора типу, ймовірно, enum, що перевіряється за допомогою switchоператора, коли потрібно виконати певну дію типу.

Інший спосіб:

Зберігання покажчиків функцій

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

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

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


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

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