Android — определить растровое изображение плитки на основе окружающих плиток

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

Моя первая попытка (показана ниже) заключалась в том, чтобы пропустить каждую плитку через серию операторов if, чтобы выяснить, какой она должна быть. Основная проблема заключается в том, что с картой мира размером 100 x 100 тайлов она будет выполняться через 10 000 итераций, получая доступ к данным на 8 окружающих тайлах (80 000 операций), а затем выполняя до четырех операторов if (320 000 операций). операции). Мне просто кажется, что это было бы ужасно неэффективно и медленно.

Преимущество этого метода заключается в том, что он будет работать только на тайлах земли и сначала будет проверяться, чтобы убедиться, что он примыкает хотя бы к одному тайлу воды, что значительно сократит количество необходимых операций.

Вот базовая диаграмма, которую я нарисовал, которая проходит через окружающие плитки и выбирает подходящую плитку.

Попытка макета 1

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

Друг рассказал мне о третьем методе, который может сработать. Он берет плитки воды и устанавливает их равными 0, а плитки земли, которые установлены равными 1. Затем он берет окружающие плитки и нумерует их от 1 до 9. Оттуда они проходятся по ним и создают строку из 0 и 1:

W   W   W
W   L   L
L   L   L

будет: 000011111

0*2^0 + 0*2^1 + 0*2^2 + 0*2^3 + 1*2^4 + 1*2^5 + 1*2^6 + 1*2^7 + 1*2^8

0*1 + 0*2 + 0*4 + 0*8 + 1*16 + 1*32 + 1*64 + 1*128 + 1*126 = 496

Теория состоит в том, что я бы присвоил плитке, связанной с этой комбинацией, номер 496 и загрузил бы ее в ответ. Проблема в том, что каждое ребро имеет 13 или 14 комбинаций, которые приведут к его использованию. например:

W   W   L           L   W   W
W   L   L    and    W   L   L   Both need the same tile as the above example, but
L   L   L           L   L   L   produce different numbers.

По сути, чтобы заставить этот метод работать, мне нужно было вычислить окончательное число для каждой возможной комбинации воды и земли, которая дала бы конкретную плитку, а затем прогнать окончательное число через серию «если/случай», чтобы выбрать подходящее. битовая карта. Это было бы так же или даже более неэффективно, чем блоки if.

Итак, подходя к главному вопросу во всем этом. Кто-нибудь знает альтернативный способ сделать это или способ сделать любой из этих методов более эффективным?


person Patrick Reynolds    schedule 18.05.2012    source источник
comment
Вы уже пробовали любое решение и проверили его на скорость? Вы уверены, что не пытаетесь выполнить преждевременную оптимизацию?   -  person zarthross    schedule 19.05.2012
comment
Еще нет, у меня не было возможности. Я ищу альтернативный метод, основанный на предположении, что выполнение всех этих операторов if займет очень много времени. Я возьму пропуск по первому методу сегодня вечером.   -  person Patrick Reynolds    schedule 19.05.2012
comment
@Zathross Что ж, похоже, ты был прав. Я провел его через начальное тестирование, и общее время возврата для прохождения каждого квадрата на карте, сбора информации об окружающих тайлах, проверки наличия воды и последующего назначения правильного растрового изображения занимает в среднем колоссальные 60 мс. Однако, как только я посмотрел на это в игре, я понял, что я далеко не учел все возможные конфигурации земли и воды. Я, вероятно, удвою или утрою количество необходимых плиток, что может привести к повторной попытке с третьим методом.   -  person Patrick Reynolds    schedule 19.05.2012


Ответы (1)


На самом деле я только что написал эту часть игры, над которой начал работать. Мне потребовалось некоторое время, чтобы обдумать решение, но когда я это сделал, я не мог поверить, что не подумал об этом раньше. Если подумать, у каждой плитки есть 8 возможных «соединений»:

1 2 3
4 x 5
6 7 8

И каждое соединение может либо содержать плитку, с которой оно соединяется, либо нет. Так что это мило, это означает, что это очень двоичная система, и мы можем представить каждую комбинацию 8 битами (или 1 байтом), и мы знаем, что каждая комбинация представлена ​​​​последовательно от 0 до 255, поэтому мы можем легко использовать таблицу поиска (ну , массив поиска), чтобы найти правильное изображение. Хотя это означает, что существует 256 возможных комбинаций соединения (не 256 различных изображений, заметьте, как вы сказали выше, разные комбинации будут использовать одну и ту же мозаичную графику), которые мы должны сгенерировать. Что я сделал (и рекомендую), так это написал небольшой скрипт для создания массива поиска.

Теперь способ поддерживать это заключается в том, что каждая плитка имеет массив из 8 длин плиток, к которым она подключена. При загрузке карты заполняйте массив плиток «connections» по мере продвижения. Как только плитка имеет все свои соединения (или когда все плитки загружены), вычислите «маску соединения» или «значение соединения» для каждой плитки (которая является индексом в массиве поиска). Это делается путем перебора массива «connections» и построения маски с использованием битовых сдвигов. После этого вам нужно будет снова выполнить очень минимальную обработку, и только на отдельных плитках, которые добавлены/удалены/изменены, и 8 возможных плитках, к которым они подключены.

Надеюсь это поможет. Если вам нужна дополнительная информация или пример кода, я могу предоставить его позже!

person poiuy_qwert    schedule 27.10.2013