Students Save 30%! Learn & create with unlimited courses & creative assets Students Save 30%! Save Now
Advertisement
  1. Game Development
  2. Game Physics
Gamedevelopment

Фізика основної 2D платформер, частина 6: реагування на об'єкт з об'єктом зіткнення

by
Difficulty:BeginnerLength:LongLanguages:
This post is part of a series called Basic 2D Platformer Physics .
Basic 2D Platformer Physics, Part 5: Object vs. Object Collision Detection
Basic 2D Platformer Physics, Part 7: Slopes Groundwork

Ukrainian (українська мова) translation by Tanya Ira (you can also view the original English article)

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

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

Демо було опубліковано в єдності 5.4.0f3, і вихідний код також сумісний з цією версією єдності.  

Відповідь Зіткнення 

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

 Покрити додаткові відомості

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

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

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

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

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

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

З'їхати перекриття 

 Давайте створимо функцію UpdatePhysicsResponse, в якому ми будемо обробляти об'єкт і об'єкт відповіді.

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

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

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

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

Почнемо пройшовшись по всім нашим даними зіткнення зараз. 

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

 Як вже зазначалося раніше, показник того, що об'єкти зворушливо, що перекриття по одній з осей дорівнює 0. Давайте почнемо з перевірки X-осі.

 Якщо умова є істинним, ми повинні переконатися, що інший об'єкт знаходиться на лівій або правій стороні нашого ААВВ.

Нарешті, якщо це праворуч, потім встановити mPushesRightObject true і встановити швидкість, так що це не більше, ніж 0, тому що наш об'єкт більше не може рухатися вправо, так як шлях перегороджує. 

Давайте розберемося з лівої сторони таким же чином. 

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

Давай розберемося по осі Y таким же чином. 

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

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

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

When we bump into another object the other object should not move

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

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

When we bump into another object the other object should not move even if its coming vertically

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

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

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

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

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

Інша справа, коли speedSum на вісь X дорівнює нулю. У цьому випадку ми вичислити правильний коефіцієнт для осі Y, і встановити, що ми повинні перейти 50% перекриття по осі X. 

 Аналогічним чином ми обробляємо випадок, коли speedSum нуль тільки на осі Y, і на останньому випадку ми розраховуємо як співвідношення правильно.

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

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

У першому випадку, ми хочемо з'їхати перекриття по осі X, у другому випадку ми хочемо з'їхати перекриття по осі Y, і в останньому випадку, ми хочемо з'їхати перекриття на якій би осі не перетинаються. 

Looking at our paths coming from each direction

 Пам'ятайте, що перекриває інший об'єкт, нам потрібен AABBs, щоб перекривати один одного на обидві осі X і y. Щоб перевірити, чи справді ми зіткнулися об'єкт горизонтально, ми побачимо, якщо в попередньому кадрі ми вже були перекриваються об'єкту по осі Y.  Якщо це так, і ми не перетинаються по осі X, то перекриття повинно було статися, адже в поточному кадрі AABBs почали перетинатися на осі X, і тому ми утримуємо, що ми врізалися в інший об'єкт по горизонталі.

По-перше, давайте порахуємо, якщо ми перекривається з іншими ААВВ в попередньому кадрі. 

 Тепер давайте створимо умови для переміщення з перекриття по горизонталі. Як пояснювалося раніше, нам потрібно перекриваються на осі Y та не перекриваються на осі X у попередньому кадрі.

 Якщо це не так, то ми будемо рухатися перетинаються на осі ординат.

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

Але ми хочемо вийти з перетинатися на осі в разі удару по діагоналі, тільки якщо перетинаються по осі X менше перетинаються на осі ординат. 

Ось і всі справи вирішено. Тепер нам потрібно вивести об'єкт із перекриття. 

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

Вертикальна корекція здійснюється таким же чином. 

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

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

Vertically landing on a group of objects

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

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

 І, нарешті, давайте зміщення накладаються один на послідовних зіткнень на сукупний вектор поправок ми зробили досі.

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

Vertically landing on a group of objects

 Тепер, що наша функція готова, давайте переконаємося, що ми використовуємо його. Гарне місце для виклику цієї функції буде після CheckCollisions дзвінок. Це вимагає від нас, щоб розділити функції нашого UpdatePhysics на дві частини, так давайте створимо другу частину прямо зараз, в класі MovingObject.

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

 Тепер, в основний ігровий цикл оновлення, назвемо другий частини фізики оновлення після CheckCollisions дзвінок.

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

Резюме 

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

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

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

 Звичайно, завжди є місце для вдосконалення, тому, якщо у вас є питання або відкликання про те, щоб зробити щось краще, або просто мати свою думку на уроці, не соромтеся використовувати розділ коментар, дайте мені знати!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.