ТРОХИ 3D-ФІЗИКИ – РОЗРОБКА ІГОР ДЛЯ ОС ANDROID

&nbsp

У цьому розділі ми використовуємо дуже просту і досить обмежену фізику Розробники ігор ідуть на все, щоб позбутися від складних обчислень Поведінка обєктів у грі не повинно бути на 100% фізично точним, воно просто має бути достатньо реалістичним, щоб виглядати правдоподібно Іноді ми навіть не хочемо, щоб поведінка була повністю фізично достовірним (наприклад, один набір обєктів повинен падати вниз, а інший такий же – вгору)

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

Ньютон і Ейлер – друзі навік

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

Розглянемо властивості нашого обєкта

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

Швидкість обєкта – це зміна місця розташування в секунду Швидкість дається як двомірний вектор швидкості, який являє собою поєднання вектора напряму (довжиною в одиницю) в сторону, в яку направляється обєкт, і швидкості в метрах в секунду, з якою рухається обєкт Зверніть увагу, що швидкість управляє тільки довжиною вектора швидкості Якщо ми нормалізуємо вектор швидкості, ми отримаємо вектор напрямку довжиною в одиницю

Прискорення обєктів – це зміна їх швидкості в секунду Ми можемо висловлювати це чи в СКАЛЯРИЯ, які просто відображають швидкість (довжину вектора швидкості) або як 20-вектор, щоб у нас було різне прискорення по осях х та у У даному випадку ми виберемо другий варіант, оскільки він спрощує роботу з такими речами, як балістика Фактично прискорення вимірюється в метрах в секунду за секунду (м/с2) Ні, це не опечатка, ми дійсно змінюємо швидкість на якесь значення, що вимірюється в метрах в секунду кожну секунду

Коли у нас є ці властивості обєкта для заданого моменту часу, ми можемо поєднати їх, щоб емулювати шлях обєкта в світі з плином часу Може здатися, що звучить це страшнувато, але ми вже надходили так з Містером номом і нашому BobTest У тих випадках ми просто не використали прискорення, ми встановлювали швидкість з фіксованим вектором Ось як можна інтегрувати прискорення, швидкість і місце розташування обєкта:

Цей феномен також називається Ейлерова числова інтеграція, і це найбільш зрозумілий метод інтеграції з усіх використовуваних в іграх Ми починаємо з точки (0, 0), при цьому швидкість дорівнює (0, 0), а прискорення – (0 -10) Це означає, що швидкість буде зростати на 1 метр в секунду по осі у По осі х руху не буде Перед тим як почнеться цикл інтеграції, обєкти будуть перебувати в стані спокою Усередині циклу спочатку оновлюємо швидкість, засновану на прискоренні, помноженому на дельту часу От і все, що ховається за таким розумним словом інтеграція

ПРИМІТКА

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

Сила і маса

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

Сила = маса х прискорення

Ми можемо перетворити це в таке рівняння:

Прискорення = сила х маса

Сила виражається в одиницях СІ – ньютонах (здогадайтеся, хто їх придумав) Якщо ми визначаємо прискорення як вектор, ми також повинні визначати силу як вектор Таким чином, сила може мати напрямок Наприклад, сила гравітації спрямована вниз (0 -1) Прискорення також залежить від маси обєкта Чим більше маса обєкта, тим більшу силу нам потрібно застосувати, щоб вона прискорювалась так само швидко, як і обєкт меншої ваги Це прямий наслідок попереднього рівності

Однак для простих ігор ми можемо ігнорувати масу і силу і працювати безпосередньо зі швидкістю і прискоренням У попередньому псевдокоде ми задали прискорення на (0 -10) метрів в секунду за секунду (знову повторюю, це не помилка), що приблизно дорівнює прискоренню, яке зазнає обєкт, падаючи на землю незалежно від його маси (ми не беремо до уваги опір повітря) Це дійсно так, Галілей підтвердить

Маніпулюємо теоретично

Використовуємо наш попередній приклад, щоб поекспериментувати з обєктом, падаючим вниз на Землю Припустимо, що ми пройшли цикл 10 разів і що getDeltaTimeO завжди дорівнюватиме 0,1 секунди Ми отримаємо такі розташування і швидкості для кожного рази:

За 1 секунду обєкт падає на 5,5 м і має швидкість (0 -10) м / с, прямуючи прямо до кори Землі (звичайно, до тих пір, як він вдариться об землю)

Обєкт постійно збільшує швидкість падіння, оскільки ми не беремо до уваги фактор опору повітря (Як я говорив раніше, в нашій системі нам ніхто не забороняє трохи шахраювати) Ми можемо легко дізнатися поточну максимальну швидкість, подивившись на довжину вектора швидкості

Всезнаюча Вікіпедія повідомляє нам, що людина у вільному падінні може досягти максимальної швидкості 125 миль на годину Якщо перевести це в метри в секунду (125 х 1,6 х 1000/3600), ми отримаємо 55,5 м / с Щоб зробити нашу емуляцію більш реалістичною, ми можемо змінити цикл таким чином:

Оскільки швидкість нашого обєкта (довжина вектора швидкості) менше, ніж 55,5 м / с, ми збільшимо швидкість за допомогою прискорення Коли ми досягли максимальної швидкості, ми просто більше не збільшуємо її прискоренням Таке просте лімітування швидкостей використовується в безлічі ігор

Ми могли б додати вітер в рівняння, вказавши ще одне прискорення по осі х, припустимо (-1 0) м/с2 Для цього нам потрібно просто додати гравітаційне прискорення і прискорення вітру перед тим, як ми додамо все це до швидкості:

Ми можемо також не враховувати взагалі ніякого прискорення і задати обєктам фіксовану швидкість Саме так ми раніше надходили в BobTest Ми змінювали швидкість кожного Боба, якщо він торкався краю

Маніпулюємо на практиці

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

Коли користувач водить пальцем по екрану, гармата слід за ним Так ми визначаємо кут, під яким вистрілимо ядром

Коли ми отримуємо подія торкання, вистрілюємо ядром в сторону, куди спрямована гармата Початкова швидкість ядра буде слідувати з напряму гармати і початкової швидкості ядра Швидкість дорівнює відстані між гарматою і точкою дотику Чим далі ми торкаємося, тим швидше ядро ​​буде летіти

Ядро буде летіти до тих пір, поки не зявиться нова подія торкання

Ми вдвічі збільшимо розмір конуса відображення від (0, 0) до (9,6 6,4), щоб ми могли бачити більшу частину світу Крім того, розмістимо гармату в (0, 0)

Зверніть увагу, що всі одиниці в ігровому світі даються в метрах

Ми визуализируем ядро ​​як червоний квадрат розміром 0,2 х 0,2 м, що дорівнює 20 х 20 см Як мені здається, досить схоже на справжнє ядро Звичайно, якщо серед вас є каноніри, ви можете вибрати розмір пореалістічнее

Спочатку місце розташування ядра буде (0, 0) – таким же, як у гармати Швидкість також буде дорівнює (0, 0) Оскільки ми застосовуємо гравітацію в кожному оновленні, ядро ​​просто падатиме прямо і вниз

Коли отримано подія завершення торкання (touch up), ми знову задаємо положення ядра в точку (0 0), а його швидкість – в значення (Math cos (cannonAngl е) Math Sin (cannonAngle)) Це гарантує, що ядро буде летіти в сторону, в яку спрямована гармата Ми також ставимо швидкість, просто помножимо швидкість на відстань між точкою дотику і гарматою Чим ближче точка дотику до гармати, тим повільніше буде летіти ядро

Звучить досить просто, реалізуємо це Я скопіював код з CannonTest в новий файл CannonGravi tyTest Java Перейменував класи, які знаходяться в цьому файлі в CannonGravityTest і CannonGravityScreen

У лістингу 83 показаний CannonGravityScreen

Лістинг 83 Фрагмент з CannonGravityTest

Не так вже й багато змінилося Ми просто вдвічі збільшили розмір конуса відображення і відобразили це, встановивши FRUSTUM WIDTH і FRUSTUMHEIGHT на 9,6 і 6,2 відповідно Це означає, що ми можемо бачити в нашому ігровому світі прямокутник розміром 9,2 х 6,2 Оскільки ми також хочемо намалювати ядро, я додав ще один екземпляр класу Vertices, який називається bail Vertices, який піде містити 4 вершини і 6 індексів прямокутника ядра Нові елементи bal 1 Pos-і bal1 Velocity містять положення і швидкість ядра, а елемент gravity – це гравітаційне прискорення, яке є константою (0 -10) м/с2

У конструкторі просто створюємо додатковий екземпляр класу Verti ces для прямокутника гармати Знову визначаємо його в просторі моделі з вершинами (-0,1 -0,1), (0,1 -0,1), (0,1 0,1) і (-0,1 0,1 ) Малюємо із застосуванням індексів, так що в цьому випадку також визначаємо шість вершин

Метод update також змінився незначно Підрахунки точки дотику в координатах світу і кута гармати залишаються колишніми Перше доповнення полягає в конструкції if всередині циклу обробки подій Ееслі ми отримуємо подія завершення торкання, то готуємо наше ядро ​​до пострілу Спочатку перетворимо кут гармати в радіани, для цього використовуємо FloatMathcos і FloatMathsin Потім підраховуємо відстань між гарматою і точкою дотику Це буде швидкість ядра Після цього встановлюємо місце розташування ядра в положення гармати Нарешті, підраховуємо початкову швидкість ядра Застосовуємо синуси і косинуси, як ми обговорили це вище, щоб створити напрямок вектора з кутка гармати Множимо цей вектор на швидкість ядра, щоб отримати кінцеву швидкість ядра Це цікаво, оскільки ядро ​​з самого першого моменту буде мати швидкість У реальному світі ядро, звичайно, прискорювалося б від 0 м / с до тієї швидкості, яку могло б досягти з урахуванням опору повітря і сили, застосованої до нього з боку гармати Ми можемо тут схитрувати, оскільки це прискорення буде відбуватися за дуже короткий проміжок часу (пара тисячних секунди) Остання деталь, яка виконується в методі update, – оновлення швидкості ядра і залежно від цього зміна місця розташування

У методі present ми просто додаємо візуалізацію прямокутника ядра Ми робимо це після візуалізації трикутника гармати, що означає, що нам потрібно очистити модельно-видову матрицю до того, як ми визуализируем прямокутник Робимо це за допомогою glLoadIdentity, а потім використовуємо glTranslatefO, щоб перетворити прямокутник ядра з простору моделі в простір світу, щоб ядро ​​потрапило в ту точку, в якій повинно знаходитися

Якщо ви запустите приклад і торкнетеся екрана кілька разів, ви добре зрозумієте, як літає ядро На рис 87 показаний результат (який, звичайно, не особливо вражає, оскільки це просто схематична картинка)

Рис 87 Трикутна гармата, яка стріляє червоними прямокутниками Вражаюче

Цією фізики цілком вистачить для наших цілей З даної простою моделлю ми можемо створити набагато більше ядер Наприклад, Супер Маріо був в основному створено так само Якщо ви колись грали в Супер Маріо, ви помітили, що Маріо потрібно небагато часу, щоб досягти максимальної швидкості при бігу Це реалізується за допомогою дуже великого прискорення і лімітрірованія швидкості, як і в попередньому псевдокоде Стрибки можна реалізувати таким же способом, яким ми запускаємо ядра Поточна швидкість Маріо буде скоригована початковим збільшенням швидкості по осі у (не забувайте, що ми можемо складати швидкості так само, як і будь-які інші вектори) Якби під його ногами не було землі, ми б застосували гравітаційне прискорення, щоб він знову впав на землю Швидкість по осі х не залежить від швидкості по осі у Ми також можемо натискати кнопки вліво і вправо, щоб змінити швидкість по осі х Краса цієї простої моделі полягає в тому, що вона дозволяє нам реалізувати складну поведінку за допомогою дуже малої кількості коду Ми будемо використовувати той же тип фізики при написанні нашої наступної гри

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

Джерело: Mario Zechner / Маріо Цехнер, «Програмування ігор під Android», пров Єгор Сидорович, Євген зазноби, Видавництво «Пітер»

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*