Біблія рухів Doom. Частина 1

Здравствуйте і ласкаво просимо в Біблію рухів Doom! У статті розібрані і розсортовані по категоріям усі примхи і капризи коду рухів в Doom, включаючи хитромудрі трюки з описом їхньої роботи.



Метрика

Почнемо з засад. Код системи для рухів гравця в Doom має наступний вигляд:
  • Збір вихідних даних гравця
  • Застосування векторів рушійної сили до гравця на основі вихідних даних
  • Стиснення швидкості гравця, якщо вона надто велика
  • Перевірка, розрахунки та переміщення
  • Використання прискорення через тертя для наступного руху гравця
Розглянемо детальніше.
Завдяки тільки цьому і парі змінних ми зможемо визначити можливі максимальні швидкості персонажа гравця.

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

За кожний твк гравець отримує поштовх рівний 0.03125 одиниць у розрахунку від величини введеної команди. Оскільки команди (зазвичай) обмежуються максимумом 50. Це дає нам максимальне прискорення тертя в 1.5625 одиниць/твк^2.

Після розрахунку руху за тик, гравець сповільнюється з допомогою коефіцієнта тертя. Конкретне значення становить 0.90625 — іншими словами, кожен рух гравця сповільнюється на 90.625% від його поточної швидкості.

Для рівнозначності прискорення і уповільнення кожного тика, зі швидкістю 50, нам потрібно знайти «х» при (1 — 0.90625)x = 1.5625. Це виводить нас до теоретичного піку прогресивної швидкості руху в 16.666 одиниць за тик. (Зверніть увагу, що фактична емпірична максимальна швидкість, з певних причин, становить трохи менше цього значення. Але все ж таки вона досить близька до зазначеного показника).

Також зверніть увагу, що гравець має незмінну максимальну швидкість, задану кодом. Ще до того як проводити фактичне обчислення руху гравця, на початку коду гра перевіряє не перевищують X — і Y-координати показник швидкості в 30 одиниць/рух^2 (або менше ніж -30). Якщо перевищує, то гра скорочує швидкість до 30 (або до -30 відповідно). Ми не будемо зациклюватися на ліміт швидкості, але слід звернути увагу, що це відбувається тільки перед початком коду руху і не перешкоджає досягненню швидкості понад 30 всередині самого коду руху.



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

Strafe running

Ще одна примха движка Doom (як, власне, і безлічі інших ігрових движків) полягає в тому, що X — і Y-координати зберігаються і обчислюються окремо. Це призводить до одному невеликому, але цікавого ефекту. Коли гравець одночасно рухається вперед і в сторону, в розрахунок застосовуються обидва вектора руху і напрямок загального руху отримує більшу величину, ніж у векторах окремо.

В нормальному геймплеї Doom стрейф має максимальну рушійну силу в 50 одиниць, а при бічному русі — 40. Таким чином при стрейфе показник рушійної сили через тік досягає 1.25 одиниці, а максимальна швидкість — 13.333 одиниць/рухів. Якщо розглянути вектори бічного і прямого руху як сторони прямокутного трикутника, Ви виявите, що максимальна теоретична швидкість при стрейфе дорівнює 21.34 одиницям за рух. А це на 28% вище звичайної швидкості, що вже досить не погано.

«SR50» strafe running

Але існує спосіб рухатися ще швидше. Згідно деяким особливостям коду, є можливість затиснути одночасно відразу кілька клавіш таким чином, щоб отримати рушійну силу при стрейфе в 50 одиниць, замість 40. Таким чином у Вас з'являється можливість розігнатися до максимальної швидкості в 23.57 одиниць/рух (тобто на 41% вище звичайної швидкості при нормальному бігу на 10% — при стрейф бігу).

Таке розмаїття стрейф бігу за досить загадкових причин зазвичай пов'язують з абревіатурою «SR50». Професіонали по швидкісному проходженню ігор створили різні інструменти, що застосовуються для аналізу демо-версій. І з допомогою деяких інструментів можна розібрати кожен тик. Власне, одна з команд-творців називалася «SR» — стрейф вправо (strafe right), за яким слідував аргумент команди. Оскільки ця техніка дозволяла досягати стрейф бігу з показником в 50 замість 40, інструменти показували команди «SR50» замість «SR40». Саме «SR50» і стала широко використовуватися як синекдоха для даної техніки.

О, і ще, так би мовити, для майбутніх поколінь — давайте вирахуємо максимальну швидкість бігу в «реальному світі»:

23.57 одиниць/рух * 35 рухів/секунду = 825 одиниць/секунду
825 одиниць/секунду/16 одиниць/фут (загальний коефіцієнт перерахунку) = 51.5 футів/секунду
51.5 футів/секунду = 35 миль в годину (близько 56 км/год).

Skip glide



трюк на 0:02

Тепер давайте перейдемо до конкретних прийомів. Перший з них вважається найбільш складним для виконання на практиці. Але в той же час, його найпростіше пояснити з позиції движка. Я називаю цей трюк «skip glide» (стрибок зі ковзанням) хоча іноді його ще називають «bar glide», що може створити плутанину, оскільки існує інший трюк з такою ж назвою.

Щоб зрозуміти цей трюк, спочатку потрібно розібрати основний спосіб, з допомогою якого Doom намагається обробляти руху. У кожному твк DoomGuy має певну x — і y-координати імпульсу (напрямок інерції). Втім я не буду називати це "імпульсом", так як подібний термін передбачає певні властивості, яких Doom не має (Ви можете рухатися за межі можливостей "імпульсу", або навпаки, у Вас може бути "імпульс" навіть якщо руху не відбувається зовсім). Замість цього я буду говорити про «імпульс» з точки зору потенційно нової позиції, яку гравець хоче перейти і посилатися на нього як на «Стан Спроби Телепортації» (Teleport Attempt Position) або СПТ. (З цього моменту зустрічаючи в тексті скорочення «СПТ», Ви можете подумки замінювати його на «імпульс». Але я сподіваюся, використання іншого терміна допоможе Вам запам'ятати, що насправді це — не «реальний» імпульс, а якийсь химерний псевдо-аналог, що має інші властивості.)

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

Ця особливість допомагає зрозуміти як саме працює «skip glide». Розглянемо канонічний приклад з Doom 2 при проходженні Map 21. Гравець займає цілком природну позицію прямо перед діагональним заслоном, який закриває щілину. На наступному тику движок проводить тест, щоб визначити, чи можна переміщувати гравця на позицію відразу *за* діагональним заслоном. При ретельному виборі напрямку можна визначити позицію, яка не буде суперечити умовам «телепорту» і движок перенесе гравця на бажану точку без будь-яких проблем.

Squeeze Glide



трюк на 0:25

Також в арсеналі є інший, ще більш поширений трюк, який пов'язаний з прийомом «bar glide», тому що він теж заснований на рух між заслонами, розташованими на відстані 32 одиниці. Для мене ж термін «squeeze glide» (ковзання з «протискиванием») здається більш адекватним для запам'ятовування і менш запутывающим.

Для squeeze glide гравець повинен ідеально вирівнюватися з зазором, однакового з персонажем розміру (32 одиниці). Потім, після низки безуспішних спроб, триваючих, як здається, цілу вічність, йому нарешті вдалося втиснутися в цей зазор!

image

У теорії «squeeze glide» повинен бути цілком простим і зрозумілим: гравець має ширину 32 одиниці (вздовж осей). Отже якщо Ви знаходите простір, чітко вирівняне по осях і з шириною 32 одиниці, то повинні бути в змозі пройти через нього. Але з движком Doom рідко буває все так просто.

Основна проблема полягає в тому, що рух у движку Doom квантування і крім того, воно квантованного не повністю. Я не буду вдаватися в подробиці і розповідати як був знайдений вектор руху гравця. Але якщо коротко, вектор використовує синуси і косинуси для об'єднання напрямки гравця з векторами руху, щоб зрівнятися з завершальними X — і Y-векторами рушійної сили. Наприклад, коли гравець затискає клавішу вперед і прямує на північ, X-координата вектора руху повинна становити значення, помножене на косинус 90, що необхідно для обнулення. На жаль, Doom не сильний в збереженні і косинусів кутів, він використовує розрахункові таблиці значень і, як виявилося, таблиця синуса/косинуса фактично не включає 0 як значення (найбільш близьке ±0.0002).

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

Отже, знаючи про те, як для гравців працює СПТ, Ви можете побачити, що відбувається:
  • Гравець намагається переміститися в просторі безпосередньо між перешкодами
  • Движок використовує СПТ, що має деякий квантованый коефіцієнт подовження, і визначає можливість переміщення в ту чи іншу позицію
  • Оскільки зазор має ту ж ширину, що і гравець, останній повинен ТОЧНО відповідати проходимому простору (неточні значення кута роблять завдання реально складною). Це означає, що для вдалого проходження Вам необхідно з ідеальною точністю в 0.0002 одиниці знаходитися на захід від місця між перешкодами
Розуміння того, як змусити злагоджено працювати squeeze glide — це не наука, а справжнє мистецтво. Спидраннеры годину за годиною вивчають тонкощі переміщення, щоб виконувати його за розумну кількість часу

Line skipping (south / west)



трюк на 19:06

Розуміння того, як движок використовує СПТ гравців для тестування нової позиції, лише трохи наблизить нас до розуміння line skip (пропуску кордону). Може здатися, що гравець робить неможливе, коли виконує line skip: біжить безпосередньо через лінію кордону без її фактичної активації.

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

Отже, заданий алгоритм. Як Ви можете обійти його? Ну, от якось так.

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

Отже, Ви бачите, що поки переміщаєтеся швидше, ніж половина ширини гравця за тик (маючи гарне розташування та дещицю удачі), немає нічого неймовірного в тому, щоб проскочити лінію кордону без її активації спеціальних дій. Тим не менш, пам'ятайте, що обмежує коробка гравця завжди вирівнюється з прив'язкою до осей координат. Іншими словами цей прийом простіше виконати уздовж осей, де «радіус» гравця становить 16 одиниць. Однак, навіть по діагоналі в 45 градусів, де «радіус» гравця становить 22.6 одиниць, стрейф біг SR50 з його 23+ одиницями за рух все ще виконаємо.

Хочу звернути Вашу увагу на те, що описане вище стосується лише руху на «південь/захід». З причин, які ми ще не обговорили, цей прийом НЕ БУДЕ ПРАЦЮВАТИ, при русі на північ або схід.

Item натикаючись



трюк на 0:16

Ось ще одна безглуздість, яка відбувається з-за дивною і химерної перевірки Doom потенційно нової позиції гравця. Алгоритм будується наступним чином:
  • Використовується СПТ гравця для визначення потенційно нової позиції
  • Перевіряється, чи немає яких-небудь перешкод у зоні посадки для того, щоб зайняти цю точку
  • Одночасно з цим проводиться перевірка на наявність яких-небудь інших речей, що перекривають зону посадки
  • І також, якщо до якоїсь з цих речей можна дотягнутися, то гравець підбирає їх
Ви бачите проблему? Гравець візьме речі, які стосуються потенційної зони посадки СПТ, навіть якщо переміщення в кінцевому рахунку не відбувається. Це означає, що якщо Ви мчите на повній швидкості в непрохідну межу c об'єктом, розташованим безпосередньо по іншу сторону від неї, движок (у момент зіткнення з кордоном) зробить спробу перемістити гравця (СПТ) по іншу сторону стіни. Це дасть можливість підібрати будь-які речі, які попадуться на місці потенційного посадки.

image

Monsters opening doors



трюк на 0:09

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

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

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.