Обновление освещения в тайловой игре

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

Теперь рассмотрим такую ​​ситуацию: игрок выкапывает яму в земле, выставляя блок, находящийся глубоко в земле, на солнце. Это дает ему уровень освещенности 16 из 16, а его соседям уровень освещенности 15. Однако, если игрок снова заполнит отверстие, блок останется с уровнем освещенности 16. Моей первой мыслью было «аудитить». " уровень освещенности блока при его обновлении путем проверки того, что он не отличается более чем на одну единицу от уровня его соседей, но это оказалось неэффективным.

Единственным решением, которое я мог придумать, было бы специально проверить, подвергается ли размещенный блок воздействию солнечного света, и если да, то обновить уровень освещенности блока под ним до 15 из 16. Однако это не было бы эффективным для исправления ошибки. проблема в определенных ситуациях, и соседние блоки не смогут уменьшить уровень освещенности из-за соседних блоков. Возможно, мне просто нужно немного отступить и еще раз взглянуть на проблему, но я подумал, что тем временем могу опубликовать здесь. У кого-нибудь есть предложения, как обойти это?


person Max Roncace    schedule 01.09.2013    source источник
comment
Я сейчас работаю именно над такой проблемой. Мое решение состояло в том, чтобы выяснить, как далеко может распространиться это изменение (сколько времени потребуется, чтобы maxLight уменьшился до minLight, очистить все эти блоки и пересчитать их все).   -  person Richard Tingle    schedule 02.09.2013
comment
@RichardTingle Я могу просто реализовать это решение, а не использовать какой-то сложный алгоритм, когда ресурсы, сэкономленные в последнем варианте, столь же тривиальны, как и они.   -  person Max Roncace    schedule 02.09.2013
comment
теперь это, очевидно, просто мнение какого-то случайного человека, но я попробовал оба, и итеративный метод, если x изменяет обновление окружающих блоков, был на самом деле медленнее, чем пересчет грубой силы (очень меня удивил)   -  person Richard Tingle    schedule 02.09.2013
comment
Сосед случайно не местное (американское?) правописание соседа? Если это так, я извиняюсь за то, что навязываю вам мое правописание   -  person Richard Tingle    schedule 02.09.2013
comment
@RichardTingle Да, все в порядке. :)   -  person Max Roncace    schedule 02.09.2013
comment
@RichardTingle Мне удалось заставить его работать, дважды обновив свет каждого фрагмента; сначала начиная с верхнего левого угла, затем с нижнего правого. Если вы скопируете свои комментарии в ответ, я приму его.   -  person Max Roncace    schedule 02.09.2013


Ответы (2)


По моему опыту, наименее подверженный ошибкам и (как ни странно) самый быстрый метод — просто очистить все световые блоки в максимальном диапазоне, который может быть затронут (+-16 в вашем случае), и пересчитать их все.

Итеративный метод при добавлении света дает хорошие результаты, но я обнаружил, что он намного медленнее; предположительно из-за накладных расходов на ведение списков блоков, которые необходимо обновлять и добавлять/удалять из них по мере выполнения алгоритма. При удалении света итеративный метод также подвержен ошибкам, поскольку свет может «просачиваться обратно», как вы обнаружите; что блок, ранее находившийся в 14 световых днях, теряет связь с солнцем и, таким образом, пересчитывается; находит блок света 13 поблизости и устанавливает свой собственный свет на 12 (вместо того, чтобы все они были установлены на ноль).

Решение, которое я использовал, состоит в том, чтобы очистить все уровни освещения, а затем сделать зачистку вниз; Сбор света из 9 блоков (в 3D, 3 блоков в 2D) над каждым блоком. Свет затухает для 8 (или 2 в 2D) блоков, которые не находятся прямо над ними, и устанавливает уровень освещенности на максимальное значение из этих 9 блоков. Это позволяет свету проходить вниз под углом до 45 градусов; это может дать довольно резкие тени, которые могут быть, а могут и не быть тем, что вам нужно. Повторение взмаха вверх может смягчить резкие тени, а также установить минимальный уровень освещенности, который есть у всех блоков независимо от солнечного света.

person Richard Tingle    schedule 02.09.2013

Я думаю, проще всего будет объяснить с помощью блок-схемы:

введите здесь описание изображения

person user60561    schedule 01.09.2013
comment
Хотя это, вероятно, лучшее решение; профилируйте это, иногда большой, но простой пересчет может быть быстрее, чем небольшой более сложный алгоритм - person Richard Tingle; 02.09.2013
comment
К сожалению, когда я пытаюсь обновить освещение блока на основе уровней освещенности его соседей, в некоторых случаях оно остается прежним, хотя этого не должно быть. Эта блок-схема по существу описывает, что мой код делал до сих пор. - person Max Roncace; 02.09.2013