Атлас текстур: не лінуйся – поділися – РОЗРОБКА ІГОР ДЛЯ ОС ANDROID

До цього моменту ми використовували в наших програмах тільки по одній текстурі Що якщо ми захочемо відобразити не тільки Боба, але й інших супергероїв, ворогів, вибухи або монетки У нас може бути кілька текстур, кожна з яких містить зображення одного типу обєктів Але OpenGL навряд чи це сподобається, оскільки нам треба буде перемикати текстури для кожного обєкта, який ми відображаємо (наприклад, привязуємо текстуру Боба, відображаємо Боба, привязуємо текстуру монетки, відображаємо монетку і т д) Процес може стати простіше, якщо помістити різні зображення в одну текстуру Це і буде атлас текстур: одна текстура, що містить різні зображення Ми повинні зробити цю текстуру поточної (привязати) тільки один раз і тоді зможемо відображати обєкти будь-яких типів, зображення яких є в атласі Так ми позбавляємося від надлишку змін стану і прискорюємо реалізацію Такий атлас текстур показаний на рис 823

Рис 823 Атлас текстур

На рис 823 знаходяться три обєкти: гармата, гарматне ядро ​​і Боб Сітка не є частиною текстури – вона потрібна тільки для того, щоб показати, як я зазвичай створюю мої атласи текстур

Атлас текстур має розмір 64 х 64 пікселя, а кожна клітинка сітки має розміри 32 х 32 пікселя Гармата займає два осередки, ядро ​​трохи менше, ніж чверть осередку, а Боб поміщається в одній комірці Тепер, якщо ви згадаєте, як ми визначали межі (і графічні прямокутники) для гармати, ядра і мішеней, ви помітите, що ставлення їх розмірів один до одного дуже нагадує те, яке ми маємо на цій сітці Мішень в нашому світі має розмір 0,5 х 0,5 м, гармата – 0,2 х 0,2 м У нашому атласі текстур Боб має розміри 32 х 32 пікселя, а ядро ​​трохи менше 16×16 пікселів Співвідношення між атласом текстур і розмірами обєктів в нашому світі має бути зрозуміло: 32 пікселя в атласі рівні 0,5 м у світі

У початковому прикладі гармата мала розміри 1×1 метр, але ми, звичайно, можемо це змінити У відповідності з нашим атласом текстур, де гармата має розміри приблизно 64 х 32 пікселя, нам треба зробити гармату в нашому світі розмірами 1 х 0,5 м Зовсім просто, правда

Але чому ж я вибрав саме 32 пікселя як еквівалент 1 м в нашому світі Ми памятаємо, що ширина і довжина текстур повинні бути ступенями двох Якщо кількість пікселів одно 32, тобто ступеня 2, для відповідності 0,5 м в нашому світі дозволяє художнику легко впоратися з обмеженнями розміру текстур Це також дозволяє простіше зрозуміти співвідношення різних обєктів з нашого світу щодо піксельних зображень

Ви можете прирівняти й інша кількість пікселів до одиниці світу Наприклад, 64 або 50 пікселів до 0,5 м в нашому світі Яке ж кількість пікселів буде найкращим Це знову ж таки залежить від дозволу екрану, на якому буде відтворюватися гра Проведемо деякі підрахунки

Наш гарматний світ обмежений координатами (0, 0) в нижньому лівому кутку і (9,6 4,8) у верхньому правому куті Це відображено на екрані Зясуємо, скільки пікселів на одиницю світу нам потрібно для екрану Нього (480 х 320 пікселів в альбомному режимі):

Наша гармата, яка тепер буде займати площу 1 х 0,5 м у світі, матиме розміри 50 х 25 пікселів на екрані Ми використовуємо область 64 х 32 пікселів нашої текстури, так що трохи знизимо якість зображення гармати під час рендеринга Залежно від фільтра мініфікаціі, який ми застосовуємо для текстури, результат буде чітким і мозаїчним (GL NEAREST) ​​або трохи розмитим (GL LINEAR) Якщо нам потрібно ідеальне відображення на Нього, треба трохи масштабувати наші текстурні зображення Ми можемо встановити розмір комірки сітки 25 х 25 пікселів замість 32 х 32 Однак навіть якщо ми просто змінимо зображення атласу (або перерісуем його від руки), у нас буде зображення розміром 50 х 50 пікселів, ніяк не підходящий для OpenGL ES Нам треба буде додати додаткові ділянки зліва і знизу, щоб домогтися зображення розміром 64 х 64 пікселя (оскільки OpenGL ES вимагає, щоб ширина і довжина зображень були ступенем 2) Можна сказати, що OpenGL ES прекрасно підходить для масштабування нашого зображення текстури для Нього

Яка ж ситуація з пристроями, що мають більш високий дозвіл, як Nexus One (800 х 480 в альбомному режимі) Зробимо підрахунки для такої конфігурації екрану за допомогою наступних рівнянь:

Кількість пікселів на одиницю світу на х-і г /-осях буде різним, тому що відношення ширини і довжини нашої області видимості (9,6 / 6,4 = 1,5) відрізняється від ставлення боку екрану (800/480 = 1, 66)

Тоді ми згадували про встановлений розмір у пікселях та відношенні сторін Тепер застосуємо цю схему і виберемо ширину і довжину конуса відображення для нашого прикладу У випадку з Nexus One гармата, ядро ​​і Боб будуть трохи збільшені і розтягнуті за високого дозволу і іншого ставлення сторін Ми приймемо цей факт, оскільки хочемо, щоб усі гравці бачили одну і ту ж область нашого світу Інакше гравці з більш високим показником відносини сторін будуть мати можливість бачити більшу частину нашого світу

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

Тут і та у – текстурні координати, ахну – піксельні координати Верхній лівий кут Боба має піксельні координати (32 32) Якщо ми вставимо їх у це рівняння, отримаємо текстурні координати (0,5 0,5) Ми можемо зробити те ж саме для будь-яких інших кутів, які нам знадобляться, і, грунтуючись на цьому, призначити правильні текстурні координати для вершин наших прямокутників

Приклад

Додамо цей атлас текстур до нашого попереднього прикладу і зробимо його красивішим Боб буде нашою мішенню

Ми просто копіюємо Camera2DTest і трохи його змінюємо Я помістив копію в файл під імям TextureAtl asTest Java і перейменував два класи, що містяться в ньому, відповідно TextureAtl asTest і TextureAtl asScreen

Перше, що ми робимо, – додаємо новий член в клас TextureAtl asScreen: Texture texture:

Замість того щоб створювати Texture в конструкторі, ми створюємо текстуру в методі resume Памятайте, що текстури будуть втрачені, коли додаток повернеться зі стану паузи, так що нам знову потрібно буде відтворювати їх у методі resume:

Я додав зображення на рис 823 в папку assets нашого проекту і назвав його atl as png (Звичайно, воно не містить сітки, зображеної на малюнку)

Далі необхідно змінити визначення вершин У нас є один екземпляр класу Verti ces для кожного типу обєктів (гармати, ядра і Боба), що містить один прямокутник з чотирьох вершин і шести індексів В результаті виходять два трикутника Нам потрібно додати текстурні координати до кожної вершини відповідно до атласом текстур Ми також змінимо уявлення гармати в якості трикутника на подання як прямокутник розміром 1 х 0,5 м Ось на що ми замінюємо старий код створення вершин в конструкторі:

Кожна з наших мереж тепер складається з чотирьох вершин, всі вони, в свою чергу, мають 2D-позицію і текстурні координати Додаємо в мережу 6 індексів, визначаючи два трикутника, які хочемо рендерить Ми також трохи зменшуємо гармату по осі у Тепер вона має розмір 1 х 0,5 м замість 1 х 1 м Це також відображено раніше при створенні обєкта Cannon в конструкторі:

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

Останнє, що нам треба змінити, – метод відображення:

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

Рис 824 Удосконалення прикладу з гарматою за допомогою атласу текстур

Ось ще кілька речей, які варто знати про атласах текстур

Коли ми використовуємо GLLI NEAR як фільтр мініфікаціі та / або магніфікаціі, можуть виникнути побічні явища, при яких два зображення всередині атласу стосуються один одного Це відбувається через те, що в процесі асоціювання текстури вибирається по чотири найближчих текселов з текстури для одного пікселя на екрані Коли вибір виконується на кордоні зображення, захоплюються також текселов з сусіднього зображення в атласі Ми можемо вирішити цю проблему, створивши порожню кордон в два пікселя між нашими зображеннями Або ще краще, ми можемо дублювати прикордонний піксел кожного зображення Перше рішення, зрозуміло, простіше – треба просто переконатися, що ваша текстура залишається ступенем 2

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

Часто ми не можемо згрупувати всі зображення гри в одну текстуру Памятайте, що є максимальний розмір текстури, який залежить від пристрою Ми точно можемо сказати, що всі пристрої підтримують текстури розміром 512 х 512 пікселів (або навіть 1024 х 1024) Тому ми просто створюємо кілька атласів текстур Бажано групувати в один атлас обєкти, які будуть на екрані разом, наприклад всі обєкти першого рівня помістити в один атлас, обєкти другого рівня – у другій, всі елементи призначеного для користувача інтерфейсу – в третій і т д Продумайте логічне розміщення обєктів, перш ніж остаточно допрацьовувати ваші художні ресурси

Памятаєте, як ми динамічно малювали цифри в грі з містером номом Ми використовували для цього атлас текстур Взагалі, ми можемо виконувати будь-яке динамічне відображення тексту за допомогою атласу текстур Просто додайте всі символи, які потрібні в грі, в атлас і відображуйте їх при необхідності за допомогою декількох трикутників, показуючи потрібні символи з атласу В Інтернеті можна знайти кошти, які допоможуть вам створити так званий растровий шрифт (bitmap font) Однак для наших цілей ми будемо застосовувати метод, який використовували в прикладі про містера Нома: статичний текст буде відображений заздалегідь як єдине ціле, і тільки динамічний текст (наприклад, цифри при досягненні рекорду) буде відображатися за допомогою атласу

Ви, мабуть, помітили, що Боби зникають трохи раніше, ніж по них фактично потрапляє ядро Це пояснюється тим, що наші обмежують фігури трохи більше, ніж потрібно Навколо Боба і ядра по кордонах є трохи порожнього простору Що з цим робити Ми просто зробимо обмежують фігури трохи менше Це треба відчути, тому поекспериментуйте з ресурсами, поки сутичку не буде фіксуватися правильно Під час розробки ігор ви будете мати справу з безліччю таких тонких моментів Уміння ретельно налагоджувати гру, напевно, один з найбільш важливих навичок, крім якісного проектування різних рівнів Відчути деякі речі важко, але зате яке почуття задоволення ви відчуєте, досягнувши ідеалу На жаль, цьому я не можу вас навчити, тому що все залежить від того, як ви самі ві-дитя вашу гру Вважайте, що це та родзинка, яка відрізняє хороші ігри від поганих

ПРИМІТКА

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

Джерело: 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>

*

*