Pull to refresh

Grid Tiling: смешение нескольких тайлов

Reading time 4 min
Views 9.9K
Думаю, многие из геймдев-программистов размышляли о том, как реализовать удобный map-tiling. Только представив всевозможные комбинации смешений, можно порядочно изломать свой мозг — я несколько раз пытался изобразить какой-либо простой в использовании алгоритм, который позволял бы отображать разнообразные тайло-карты. О том, что из этого получилось — а получилось нечто достаточно простое для реализации — можно узнать ниже.

Сколько раз текстуры необходимо смешать для того, чтобы изобразить всевозможные комбинации из двух тайлов на сеточном поле? А добавляя дополнительные тайлы это количество увеличивается до таких чисел, о которых даже страшно думать. Забудем на момент о всех этих сложностях и погрузимся в рассмотрение комбинаций, чтобы выявить какие-нибудь шаблоны, которые помогут нам победить трудности смешения.



Начнем со смешения двух тайлов. На рис.1 я изобразил простейшую тайловую разметку «как есть», а на рис.2 — нечто такое, что мы хотим иметь в итоге.



На рис.3-4 можно посмотреть более сложную разметку. Количество всевозможных комбинаций достаточно велико (а мы помним о предстоящем добавлении новых тайлов), и нам нужно найти некую закономерность, которая поможет упростить задачу.

В процессе я успел нарисовать здоровенное количество этих самых комбинаций и в итоге пришел к такому решению — если разделить тайл на 4 части, то его вид можно определить всего лишь по 3 смежным тайлам. Посмотрим на 5 разных шаблонов смешения:





Маленький квадрат в желтой рамке — это часть того тайла, который мы пытаемся обрисовать. То, как он будет выглядеть, определяется смежными H-V-C-тайлами.
H — смежный горизонтально (Horizontal)
V — смежный вертикально (Vertical)
C — угловой тайл (Corner)
Пользуясь этими обозначениями можно заметить схожую закономерность и для остальных 3 частей тайла, а это значит, что придумав алгоритм для одной части, мы легко распространим его на весь тайл.

В итоге у нас есть 3 смежных тайла, что означает всего лишь 8 различных их комбинаций. Почему я изобразил только 5 шаблонов? Давайте рассмотрим эти комбинации:
HCV (все смежные тайлы того же самого типа, что и рассматриваемый): шаблон 5 (отрисовываем часть тайла «как есть»)
H-V (H и V-тайлы такие же, тайл в углу отличается): шаблон 4
--V или -CV: шаблон 3 (две комбинации мутировали в один шаблон — это упрощает дело; можете нарисовать их и посмотреть, что действительно можно обойтись только одной картинкой)
H-- или HC-: шаблон 2
--- или -C-: шаблон 1

Изначальная куча комбинаций уменьшилась до всего лишь 8 и даже больше — нам необходимо только 5 разных шаблонов для любой тайловой разметки. Причем шаблон номер 5 весьма прост — мы рисуем нашу часть тайла без какого-либо смешения. Получается, для каждой части необходимо получить 4 разные маски смешения для шаблонов 1-4. Учитывая то, что тайл мы дважды располовинили, нам понадобится маска 4х4, при помощи которой мы можем намешать разметку из двух тайлов в любых вариантах.



Маска для одной части тайла


Маска 4х4

Достаточно занудная, не так ли. Естественно, вы можете придумать что-нибудь еще более красивое; для демонстрации происходящего я буду использовать вот такую маску.
Первая картинка — это маска для той части тайла, которую мы исследовали чуть ранее, а вторая — комбинация масок для всех четырех частей:
— верхне-левая часть (порядок соответствует номерам шаблонов: 1-2-3-4)
— верхне-правая часть
— нижне-правая часть
— нижне-левая часть
Маска предстваляет собой альфа-канал для отрисовки примешиваемого тайла. То есть сначала мы отрисовываем базовый тайл, а потом при помощи маски кладем сверху соответствующую часть второго тайла.



А вот результат работы описанного алгоритма для абстрактной тайловой разметки (используя представленную маску). Конечно, вместо скучных монотонно-цветных тайлов можно использовать текстуры, а если немного поработать над маской можно получить достаточно красивую поверхность.

Резюмируя вышеописанное — алгоритм таков:
— рисуем тайл-1
— рисуем по маске тайл-2

Итак, со смешением двух тайлов будем считать что разобрались. Как насчет добавления еще парочки?

Сначала определимся с последовательностью. Хотите знать, что получится если мы заменим порядок отрисовки тайлов, то есть начнем с тайла-2, а маску положим на первый? Вот картинка:



Весьма отличается, не так ли. То есть порядок имеет значение. Мы рисуем первый тайл, а сверху накладываем второй. Какие-нибудь идеи насчет третьего? Элементарно — просто добавляем новый слой поверх той картинки, что мы получили ранее. Правда тут есть пара моментов, которые необходимо учесть.

Для начала необходимо решить, какой тайл необходимо отрисовать первым, какой вторым и так далее. Представим некое зеленое поле с выжженными пятнами желтой травы и протекающей поверх реки. Очевидно что зеленое поле мы рисуем в первую очередь. Теперь сверху кладем слой желтой травы и при этом помним о том, что нужно будет поверх добавить реку.
Вычисляя маску для разметки желтой травы необходимо считать речной тайл таким же, что и желтый (помните HCV-шаблоны? К примеру, если все эти тайлы — речные, мы считаем, что подходит шаблон номер 5). А для вычисления маски под реку все ранее отрисованные тайлы считаем чужими (в аналогичном HCV-примере нужен будет шаблон номер 1).

Последим за алгоритмом. Допустим, зеленое поле это тайл-1 (первое в стеке), желтая трава — тайл-2, а река — тайл-3.
— рисуем всю сетку тайлом-1 — генерируем маску для каждого тайла, при этом все тайлы, меньшие 2, представляют черный цвет маски (полностью прозрачный), а те, что больше или равны — белый (отрисовываются)
— рисуем тайл-2 (при этом отрисовываются все тайлы, начиная со второго, причем как тайл-2!)
— генерируем вторую маску, теперь все тайлы, меньшие 3 — прозрачные, 3 и более — отрисовываются
— рисуем тайл-3
— … (продолжаем, пока тайлы не кончатся)

Звучит просто? Особенно в сравнении со сложностью комбинирования каждой пары тайлов друг с другом. Если мое объяснение не такое шикарное, как я предполагал — просто посмотрите поэтапную работу алгоритма на скриншотах, это должно прояснить ситуацию:




(Простите за две пересекающиеся реки. Всё ради тайлинга!)

Вот такая вот основная идея. При этом можно использовать различные маски при отрисовке разных слоёв. Смешение нашей желтой травы и зеленого поля может выполняться с одной маской, а для более симпатичных речных берегов можно подобрать другую. Также можно подумать насчет дополнительной текстуры — для тех же симпатичных берегов только альфы будет недостаточно, поэтому почему бы не положить по маске аналогично размеченную специальную текстуру. В общем, есть простор для мыслей при использовании этого алгоритма, лишь бы всё это вписалось в фантазию и возможности железа. Надеюсь, вы найдете этот метод полезным, или хотя бы он навеет какие-либо свои интересные идеи!

* Небольшой постскриптум: так исторически сложилось, что эту статью я сначала написал на английском. Возможно, если бы при написании русской версии я не подсматривал на оригинал, язык был бы более человеческим; по-крайней мере я старался! В любом случае, прошу прощения за внезапные сложночитаемые обороты.
Tags:
Hubs:
+15
Comments 1
Comments Comments 1

Articles