Масштабирование ассетов в 2D-игре

Как заставить изображение выглядеть хорошо на всех экранах.

В закладки

Основатель студии 6x13 Games Кенан Болукбаси (Kenan Bolukbasi) в блоге на сайте Gamasutra рассказал о масштабировании двухмерных ассетов под разные размеры экранов и разрешения.

Масштабирование двухмерных ассетов может быть, по меньшей мере, проблематичным. Есть много способов сделать это, и выбор зависит лишь от того результата, который вы хотите достичь. Проблема в том, что вы обычно не знаете, как поведёт себя интерфейс.

Учитывайте, что большинство методов масштабирования плохо реагируют на изменение соотношений сторон экрана. Они могут хорошо работать на вашем тестовом мониторе, но потом всё развалится. Я расскажу об одном методе масштабирования ассетов, который хорошо подошёл для всех четырёх игр, которые мы выпустили.

Есть три вещи, которые вы ожидаете от своего движка:

  • ​выбор наиболее подходящей графики в зависимости от разрешения дисплея;
  • масштабирование выбранных элементов для того, чтобы они подходили под размер экрана;
  • движок позволяет вам игнорировать все проблемы с дисплеем и сосредоточиться на написании кода для самой игры.

Предположим, мы используем движок Cocos2d-x и будем использовать терминологию, принятую среди разработчиков на нём. Cocos предоставляет базовый набор инструментов, поэтому методы, описанные ниже, подойдут и для других 2D-движков.

Политика разрешения

На самом деле к разрешению она не имеет никакого отношения. Здесь дело в кадрировании.

Cocos2d-x автоматически масштабирует всю сцену под размер кадра. Именно политика разрешения (Resolution policy) позволяет вам определять, как именно сцена занимает кадр.

Вам нужна безопасная зона. Она не только показывает, какую часть экрана увидит игрок, но и занимает как можно больше пространства. Всё, что за пределами жёлтой области — всего лишь декорации, которые заменяют собой чёрные границы. За пределы этой области не стоит помещать ничего, что может быть важным для игрока.

Безопасная зона в нашем примере занимает 480х320 единиц (units), на экране в 570х360 единиц. Не пикселей, единиц. Соотношение сторон тут — 1,5f. Но как мы можем быть в этом уверены?

Мы вычисляем опорную ось (reference axis), исходя из соотношения сторон дисплея. Затем мы выбираем фиксированную высоту или фиксированную ширину, исходя из опорной ости. Если опорная Y, то фиксированной становится высота, в противном случае — ширина.

Размер композиции

Для того, чтобы Cocos смог «подогнать» сцену под размер кадра, движок должен «понимать», что именно мы считаем «сценой». Это и есть размер композиции (Design Size). В нашем случае размер композиции — это величина безопасной зоны.

Как только мы зададим размер композиции и политику разрешения, движок начнёт вести себя «как взрослый». Вот так он реагирует на изменения соотношения сторон и физического размера экрана.

Итак:

  • Cocos масштабирует под размеры экрана;
  • политика разрешения указывает, «как» подстраивать под размеры экрана;
  • размер композиции указывает, «что» подстраивать.

Поддержка нескольких разрешений

Нам надо сделать так, чтобы ассеты быстро обрабатывались, правильно использовали видео-память и могли нормально отображаться при минимальном количестве проходов алиасинга в ходе масштабирования. Для этого мы добавили ассеты разного разрешения, поместив каждый набор в отдельную директорию.

Наиболее подходящий размер мы выбираем в зависимости от размера экрана, заданного опорной осью. В пикселях. После этого достаточно добавить нужную директорию в «Resource Search Path» в движке, опуская остальные, чтобы они даже не были видны.

Фактор масштабирования контента

Мы также добавляем фактор масштабирования к каждой директории для того, чтобы движок знал, как ассеты соотносятся с размером композиции. Это просто. Например, если «средний» ассет в два раза больше значения размера композиции, то значение масштаба — 2.

На этом этапе мы можем забыть о выборе ассетов, разрешении, вариантах PPI, retina-дисплеях, необычных соотношениях сторон и прочем. Мы просто «представляем», что размер экрана — 480х320, когда пишем код. За исключением тех случаев, когда вы хотите добавить декоративные элементы за пределами безопасной зоны.

#арт

Материал опубликован пользователем. Нажмите кнопку «Написать», чтобы поделиться мнением или рассказать о своём проекте.

Написать
{ "author_name": "Андрей Верещагин", "author_type": "editor", "tags": ["\u0430\u0440\u0442"], "comments": 7, "likes": 24, "favorites": 19, "is_advertisement": false, "subsite_label": "gamedev", "id": 11216, "is_wide": false, "is_ugc": false, "date": "Sun, 08 Oct 2017 14:28:48 +0300" }
{ "id": 11216, "author_id": 22254, "diff_limit": 1000, "urls": {"diff":"\/comments\/11216\/get","add":"\/comments\/11216\/add","edit":"\/comments\/edit","remove":"\/admin\/comments\/remove","pin":"\/admin\/comments\/pin","get4edit":"\/comments\/get4edit","complain":"\/comments\/complain","load_more":"\/comments\/loading\/11216"}, "attach_limit": 2, "max_comment_text_length": 5000, "subsite_id": 64954, "possessions": [] }

7 комментариев 7 комм.

Популярные

По порядку

Написать комментарий...
–1

Чтобы не мучаться такой байдой, лучше собирать 2д игры в юнити ) там завезли новые инструменты и крутую камера в 2017.12

Ответить
0

*наконец то завезли. даже название сделали 2017, чтобы не могли говорить, что в юнити нет крутой камеры в 2к17

Ответить
2

Ну там и раньше вполне норм можно было камеру настроить, немножко смекалки и пару скриптов, а сейчас даже этого не надо.

Ответить
0

Cinemachine как бы ещё с фавраля 2016 года существует самостоятельным ассетом, так что нечего глупости говорить.

Ответить
0

Он сейчас бесплатный и его улучшают. 2д камеру вроде как недавно завезли. Во всяком случае анонсирована она как new feature

Ответить
0

Улучшали его и так не зависимо от того выкуплен он юнитеками был или нет, это не делает его новым инструментом. А уж про 2D камеру смехота, всё то же самое делается и текущей виртуальной камерой просто для особо ленивых сократили 1 дименшн в настройках.

Ответить
0

https://blogs.unity3d.com/ru/2017/10/12/unity-2017-2-is-now-available/

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

Ответить
0

Прямой эфир

[ { "id": 1, "label": "100%×150_Branding_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox_method": "createAdaptive", "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "ezfl" } } }, { "id": 2, "label": "1200х400", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "ezfn" } } }, { "id": 3, "label": "240х200 _ТГБ_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fizc" } } }, { "id": 4, "label": "240х200_mobile", "provider": "adfox", "adaptive": [ "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "flbq" } } }, { "id": 5, "label": "300x500_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "ezfk" } } }, { "id": 6, "label": "1180х250_Interpool_баннер над комментариями_Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "clmf", "p2": "ffyh" } } }, { "id": 7, "label": "Article Footer 100%_desktop_mobile", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fjxb" } } }, { "id": 8, "label": "Fullscreen Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fjoh" } } }, { "id": 9, "label": "Fullscreen Mobile", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fjog" } } }, { "id": 10, "label": "Native Partner Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyb" } } }, { "id": 11, "label": "Native Partner Mobile", "provider": "adfox", "adaptive": [ "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyc" } } }, { "id": 12, "label": "Кнопка в шапке", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fdhx" } } }, { "id": 13, "label": "DM InPage Video PartnerCode", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox_method": "createAdaptive", "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "clmf", "p2": "flvn" } } }, { "id": 14, "label": "Yandex context video banner", "provider": "yandex", "yandex": { "block_id": "VI-250597-0", "render_to": "inpage_VI-250597-0-1134314964", "adfox_url": "//ads.adfox.ru/228129/getCode?pp=h&ps=clmf&p2=fpjw&puid1=&puid2=&puid3=&puid4=&puid8=&puid9=&puid10=&puid21=&puid22=&puid31=&puid32=&puid33=&fmt=1&dl={REFERER}&pr=" } }, { "id": 15, "label": "Плашка на главной", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "byudo", "p2": "ftjf" } } }, { "id": 17, "label": "Stratum Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fzvb" } } }, { "id": 18, "label": "Stratum Mobile", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fzvc" } } } ]
10 самых лучших блюд
(согласно инстаграму Хидео Кодзимы)
Подписаться на push-уведомления