Doom engine
Doom engine («рушій Doom»), також відомий як id Tech 1 — псевдотривимірний гральний рушій, розроблений американською компанією id Software і застосовуваний у комп'ютерних іграх Doom, Heretic, Hexen, Strife, HacX та інших іграх, створених за ліцензією. Створений Джоном Кармаком, допоміжні функції були написані Майклом Абрашем[en], Джоном Ромеро, Дейвом Тейлором[en] і Полом Редеком (англ. Paul Radek). Спочатку написаний на комп'ютерах NeXT, потім, для першого релізу Doom був портований під DOS, а пізніше ще на кілька ігрових консолей і операційних систем. Відмінності від Wolfenstein 3D engine
Обмеження
Технічні особливостіРушій був написаний на Сі на робочих станціях NeXT в операційній системі NEXTSTEP. Спочатку використовувався компілятор Intel C, але в подальшому був використаний Watcom C[ru]. Утиліти були написані під NeXT на Objective-C. Рушій Doom був прогресивним для свого часу. Незважаючи на те, що Сі — мова процедурного програмування, рушій Doom написаний в явно вираженому об'єктному стилі. Будова рівнів[1]Всі рівні в Doom насправді двовимірні, що вказує на одне з обмежень рушія: неможливо мати кімнату (сектор) над іншою кімнатою. Однак, з іншого боку, це дозволяє без особливих проблем малювати карту рівня з відображенням всіх стін і об'єктів, на відміну від інших ігор цього жанру. Рівень складається з десяти блоків Рівні будуються за субтрактивним принципом: весь простір заповнений непрохідною матерією, і автор рівня «прорубує» в цій матерії тунелі. Основою рівня є вершини (англ. vertices) — точки у плоскому просторі. Між вершинами проводяться відрізки (англ. linedefs). Відрізок може мати одну або дві сторони (англ. sidedefs). Текстури задаються не для відрізків, а для сторін, так що відрізок може бути покритий з різних боків різними текстурами. Вершини і відрізки утворюють плоский граф; кожна його грань може бути або непрохідним простором (наприклад, колоною), або сектором (англ. sector). Іноді структуру секторів навмисно порушують — на цьому засновані спецефекти на зразок невидимих мостів. Кожен сектор має в плані довільну форму (не обов'язково опуклу або однозв'язну). У сектора завжди горизонтальні підлога зі стелею і постійна освітленість. Односторонні відрізки є глухими стінами, двосторонні — утворюють переходи між секторами. Щоб забезпечити найвищу на той час інтерактивність, застосовані так звані теги. Відрізок і сектор мають особливе ціле поле — «тег». Щоб зробити вимикач, який опускає ліфт, відрізку-вимикачу задаються код дії «вимикач, опускає ліфт» і який-небудь тег (наприклад, 5). Цей тег присвоюється сектору-ліфта. При активації відрізок буде виконувати вказану дію на всіх секторах з цим тегом. Нарешті, на рівні розставляються об'єкти (things). При цьому набір характеристик об'єкта в Doom виявився досить бідний: наприклад, не було Z-координати, наземний об'єкт на початку гри завжди стояв на підлозі, а повітряний — висів під стелею. Не можна зробити, щоб об'єкт був тільки в одиночній грі, або тільки в deathmatch, або тільки в кооперативній (був лише прапор «тільки в мережевих іграх»). ГраВсі обчислення проводяться з нерухомою комою 16,16, з машинною одиницею, що дорівнює одному текселю (зріст гравця 56 текселів[2][3] — отже, 1 тексель приблизно дорівнює 3 см). Для кутових величин застосовується нерухома кома, в якій 232 = 360°[2]. Втім, більшість кутових розрахунків були грубіші — наприклад, повороти гравця розраховуються з точністю до 360° = 216 = 65536, а тригонометрична таблиця складалася всього з 8192 (213) величин[2]. Запис демо-роликів і мережева гра засновані на тому, що на цифровій ЕОМ один і той самий код з однаковими даними призводить до одного і того ж результату, а поведінка цілочисельної арифметики жорстко специфікована і не залежить від моделі процесора. Гра записує демо-ролик (і передає по мережі) команди керування[2][4][5]; якщо в грі немає грубих помилок, різні машини, інтерпретуючи одні й ті самі команди керування, отримують однаковий результат. Втім, помилки, що призводять до розсинхронізації, в грі все-таки є: зокрема, якщо в одиночній грі зайти в меню, гра зупиняється, але ролик продовжує писатися[6]. Недолік такого підходу — неможливість перемотати ролик; його можна тільки програти з початку. В режимі запису демо-роликів точність поворотів знижувалася до 256 на 360 градусів[2][7]; уважний гравець може помітити, що в режимі демозапису наведення стає грубішим. Це служить виключно для економії пам'яті в демо-роликах. Кожен ігровий такт (1/35 секунди) гра проводить цикл керування кожним монстром. Щоб заощадити процесорні такти, існує бітова матриця Структура Побудова зображенняДля прискорення відображення використовується BSP-дерево[9] (на відміну від порталів в Duke Nukem 3D). Об'єкти зображуються у вигляді спрайтів, на відміну від Quake. Рушій рекурсивно проходить по BSP-дереву, вимальовуючи стіни від ближніх до дальніх[10]: функція ПрохідПоДереву(вузол) якщо ОхоплювальнийПрямокутник(вузол) не в конусі видимості то вихід якщо вузол є розвилкою то // вузол є розвилкою - рекурсивно пройти якщо камера ліворуч від січної площини то ПрохідПоДереву(вузол.лівий); ПрохідПоДереву(вузол.правий) інакше ПрохідПоДереву(вузол.правий); ПрохідПоДереву(вузол.лівий) інакше // вузол є підсектором намалювати(вузол) Тут і задіяні три блоки, що залишились. Сектори розбиваються січними на опуклі елементи, іменовані підсекторами ( Після того, як вималювано стіни, порядково малюються підлоги, записані у visplanes. В кожному секторі тримається зв'язаний список об'єктів, які знаходяться в ньому. На етапі вимальовування стін видимі об'єкти разом з точками відсічення складаються в масив. Після того, як рушій намалює підлоги і стелі, масив сортується, і найближчі 128 об'єктів малюються від далеких до ближніх з допомогою тих самих процедур, що використовуються для малювання стін. На цьому ж етапі малюються і решітки («середні» текстури на двосторонніх стінах). Текстури стін і спрайт зберігаються .WAD-файлі за стовпцями, текстури підлоги і стелі — простий масив 64×64. Doom для DOS працював у режимі VGA 320×200[11] з потрійною буферизацією[ru], для Linux — використовував звичайний режим VGA 13h. При цьому величина роздільності була закодована в асемблерних процедурах у двох місцях; версії гри, які використовували змінну роздільність, або мали кілька функцій під різні роздільності[12], або динамічно модифікували код, підставляючи потрібну роздільність[13]. Втім, у частинах гри, які до рушія не відносяться, зустрічалося вкрай багато магічних чисел, пов'язаних з роздільністю екрану і екранними координатами різних об'єктів, тому перші порти Doom страждали «розповзанням» графіки меню в SVGA-режимах[14]. Тривале завантаженняDoom відомий своїм тривалим завантаженням (більше хвилини на комп'ютерах свого часу). Основна частина часу витрачалася на ініціалізацію «демона перемальовування Doom» (англ. Init Doom refresh daemon). Doom поширювався на дискетах і через BBS, тому важливим був кожен байт. Щоб зменшити розмір, зробили такий механізм. Кожна з текстур для стін складалася з фрагментів (англ. patches): наприклад, стіна з вимикачем може складатися з картинки стіни і картинки вимикача, або плиткова стіна — з трьох-чотирьох плиток, хаотично розкиданих по великій текстурою. Текстури, як сказано вище, малюються по стовпцях. Doom проходився по всіх стовпцях всіх текстур і перевіряв, які фрагменти покривають той чи інший стовпець; будувалася відповідна структура даних. Цю структуру можна було закешувати, або будувати при завантаженні рівня, добудовуючи динамічно в міру потреби — в цьому випадку Doom завантажувався б набагато швидше[15]. Крім того, Doom мав спеціалізований метод кешування даних під назвою «зонна пам'ять». Інструкція радила відключити дискові кеші на зразок SmartDrive[ru] — в Doom є більш ефективний кеш. Мережевий кодDoom заснований на моделі «рівний з рівним». Як було сказано вище, синхронність гри на всіх машинах забезпечується тим фактом, що один і той самий код з однаковими даними повертає однаковий результат. З кожним пакетом передається «згортка синхронізації» — зазвичай координата одного з гравців; якщо отримана з пакетом згортка не збігається з локально обчисленою, гра припиняє роботу з повідомленням про розсинхронізацію. Ніяких засобів протистояння затримкам передачі немає; якщо середній пінг перевищує 1/35 секунди, сповільнюється реакція гри на керування. Гра може запитувати втрачені пакети і дублювати їх, щоб запити повторної передачі йшли якомога рідше. Входу в розпочату гру немає. Підтримка того чи іншого мережевого протоколу не включена в Doom. Для того, щоб запустити гру по мережі, гравці викликають зовнішню програму — мережевий драйвер, який налагоджує зв'язок між машинами і викликає .EXE-файл Doom. Така конструкція дозволяє писати зовнішні драйвери для інших мережевих протоколів — або програми запуску Doom по мережі, більш зручні, ніж наявні. Кожен з гравців має свій колір: перший — зелений, другий сірий, третій — коричневий, четвертий — червоний. Номери гравців (і, відповідно, кольору) роздаються мережевим драйвером, а не грою. У грі IPX через програму Цікавою недокументованою функцією версій 1.0 і 1.1 була одиночна гра на тримоніторній системі: один показує те, що спереду від гравця, другий — те, що ліворуч, третій — те, що праворуч. Оскільки відеоплат з можливістю приєднувати таку кількість моніторів на той час не існувало, для такої гри потрібні були три комп'ютери, з'єднані мережею. Втім, ця функція існувала лише в зародку: щоб завантажитися з збереження, потрібно на всіх трьох комп'ютерах перезапустити гру. Список ігор, що використовують Doom engineРушій Doom продавався іншим компаніям. На ньому було зроблено низку ігор. Серед них: Також фанатами гри створювалися користувацькі модифікації, які повністю перетворювали гру. Перша з них — Alien Doom — була зроблена за фільмом «Чужий». Згодом з'явилися модифікації й за іншими фільмами: «Мисливці за привидами», «Бетмен» і «Секретні матеріали». Відкриття сирцевого кодуУ 1994 році відкрили тексти сирців мережевих драйверів. Ентузіасти почали розробляти власні драйвери: наприклад, для LPT-кабелю ( У грудні 1997 року повний сирцевий текст Doom для Linux був опублікований під невільною безкоштовною ліцензією (версія для DOS не публікувалася через платну звукову бібліотеку DMX). Вже в січні 1998 року з'явився перший порт цього коду для DOS — DosDoom. Піонерами розширення Doom були Лі Кіллоу (Boom — розширена версія Doom, в якій були виправлені численні помилки оригінальної гри), Деніс Фабріс і Борис Перейра (Doom Legacy з підтримкою високих роздільностей), а також Брюс Льюїс (glDoom, перший порт Doom під OpenGL). Після півроку розробки поламка жорсткого диска комп'ютера Льюїса поставила хрест на glDoom: резервної копії не було. Через це Кармак переліцензував сирці під GNU General Public License: якби ліцензія не була такою обмежувальною, текст сирців обов'язково знайшовся б у когось[16]. Решта ресурсів так і залишаються платними. Через 12 років сирцевий код знайшовся — у друга, до якого Льюїс ходив з диском. В Doom було знайдено величезну кількість помилок[17]. Фізичний рушій і рендерер по-різному визначали, є площина «небесною» чи ні: ракета могла вдарити в небо і вибухнути[18], і навпаки, могла «полетіти», не вибухаючи, через глуху стіну[19]. Монстри застрягали в дверях[20], а Arch-Vile, воскрешаючи роздавлений труп, одночасно робив його невразливим і здатним проходити через стіни[21]. Зазвичай порти перевіряли версію демо-ролика: помилки вмикалися, якщо ролик записаний вихідною версією гри, і вимикалися, якщо портом. Подібні помилки на деяких користувацьких рівнях були критичні для проходження — тому в Boom і похідних портах їх можна було увімкнути через меню. Зараз існує кілька десятків розширених версій Doom — від простих до надзвичайно потужних. Вони дозволяють грати з більш високою роздільною здатністю, ніж оригінальний Doom, мають додаткові можливості (огляд вгору-вниз, перехрестя прицілу), а також розширену мережеву гру. Найбільш відомі з цих версій:
В Doom Legacy, ZDoom і SkullTag присутня можливість гри з ботами. Менш значущі модифікації коротко перелічені в списку портованих версій ігор серії Doom[en]. Файли даних Doom донині залишаються платними. Для створення повністю вільного IWAD-файлу був започаткований проект FreeDoom. Примітки
Information related to Doom engine |