Найти тему
ZDG

Пирог #12. Проблемы плиток

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

Вся подборка по рогаликам:

1. Проблема кодирования

Рассмотрим пример карты, составленной из плиток:

Плитки из бесплатного набора Mini World на itch.io, (c) Shade
Плитки из бесплатного набора Mini World на itch.io, (c) Shade

Чтобы её хранить, в каждую клетку карты надо записать какое-то число. Например, 1 это вода, 2 это трава, 3 это дорога, 4 это дерево, и т.д.

Итого, если мы хотим тратить на одну клетку один байт, мы можем иметь до 256 разных плиток в пределах одной карты, и в принципе этого должно быть достаточно.

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

-2

Поэтому на границах между двумя средами или материалами применяются плитки, в которых отрисованы переходы:

Плитки из бесплатного набора Puny World на itch.io, (c) Shade
Плитки из бесплатного набора Puny World на itch.io, (c) Shade

Здесь можно увидеть скруглённые углы, специально отрисованные границы между водой и сушей, между песком и травой, бордюры.

Но это значит, что мы уже не можем иметь одну плитку песка. Нам нужны:

  1. плитка песка
  2. плитка песка, которая граничит с водой в разных вариантах
  3. плитка песка, которая граничит с травой в разных вариантах

Для песка, травы, воды и их сочетаний нужно уже примерно столько плиток (здесь они упакованы неоптимально, но вы можете понять идею):

-4

Следовательно, количество плиток резко увеличивается (хотя по-прежнему это всего лишь три материала: песок, вода, трава). И каждой плитке нужно назначить своё число. И предыдущая оценка в 256 плиток становится совсем пессимистичной.

2. Проблема видимой доступности

Если персонаж движется по плиткам травы и песка, то он вполне себе может стоять на плитке, которая совмещает траву и песок.

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

-5

В первом варианте стена занимает часть пустой клетки (песочного цвета), и поэтому становится не вполне понятно – может персонаж заходить в такую клетку или нет? Если может, то не наложится ли его спрайт на стену? А если не может, то не будет ли выглядеть неестественно практически пустая клетка, в которую нельзя зайти?

Следовательно, предпочтительнее рисовать второй вариант, так как клетка, доступная для персонажа, остаётся полностью свободной.

Далее, если представить все возможные комбинации, которые могут присутствовать в клетках со стенами, то получим такое множество:

-6

На самом деле возможны (или нужны) не абсолютно все комбинации, но я насчитал минимум 16 и дальше просто не стал. И это всего два материала.

3. Автоматизация

Я решил автоматизировать рисование плиток следующим образом:

Если есть есть материал 1 и материал 2, и X сочетаний между ними, то каждая клетка карты хранит только 1 или 2, как будто никаких сочетаний нет.

А вот когда карта рисуется на экране, тогда для каждой клетки делается проверка – что хранится в её соседях? И в зависимости от этого в клетке дополнительно дорисовываются фрагменты стены.

Например: значение текущей клетки это "здание". Справа от неё находится пустая клетка "пол". Значит, в правой части текущей клетки дорисовываем вертикальный фрагмент стены, который отделит здание от пола. Аналогично проверяем левую сторону, а также верх, низ и углы.

Для проверки данного решения я сделал скрипт, который можно смотреть онлайн:

https://js.do/nandakoryaaa/smartmap

-7

Первоначально есть только серый квадрат, это пол. На нём с помощью мышки можно рисовать стены, а также стирать их (при нажатии на плитку пола появляется стена, а при нажатии на плитку стены – пол).

Для каждой клетки карты выполняется 8 проверок (по числу соседей). Понятно, что данный механизм довольно громоздок.

Я попытаюсь решить эту задачу более эффективным способом.