Построение теней на C#. Часть 4
В прошлый раз мы увидели, сколькими разными способами можно неверно вычислить верхнюю ячейку, основываясь на верхнем векторе. Сегодня мы вкратце взглянем на определение нижней ячейки.
Из нашей прошлой дискуссии мы выяснили, что правильный способ определить, какая самая верхняя ячейка фрагмента столбца является видимой, состоит в рассмотрении, где верхний вектор покидает столбец. Аналогично, правильный способ определить, где во фрагменте столбца расположена самая нижняя видимая ячейка, посмотреть где нижний вектор входит в столбец. Очевидно, что вектор входит в текущий столбец там, где он покидает предыдущий, а мы уже знаем, как это вычислить.
Что будет неправильно, если вы, скажем, будете округлять вниз вместо округления к ячейке, где вектор входит в столбец? В моей реализации, сделанной недавно, я допустил преднамеренную ошибку: для нижнего вектора направления я округлил результат деления вниз. Это породило некоторые артефакты. Например, это означает, что вы можете видеть непосредственно за ближайшими колоннами, но не за колоннами, расположенными удаленно:
Заметьте, как колонна слева отбрасывает полную тень на 90 градусов. Однако, колонна справа позволяет мне видеть ячейку непосредственно за ней, и затем уже отбрасывает тень. Это не слишком правдоподобно, если я могу видеть непосредственно за колонной, то почему я не могу видеть также другие ячейки за ней?
Заметьте, что это представляет проблему для сценария игры. Предположим, за колонной восточнее меня скрывается монстр. Я могу видеть монстра, но он не может видеть меня! Если прицеливание для стрел требует прямой видимости, а прямая видимость определяется вычислением всего поля зрения и проверкой, находится ли искомая ячейка в этом поле зрения, то тогда я могу стрелять в монстра, а он в меня нет. Аналогично, монстр, расположенный на две ячейки западнее меня за колонной может стрелять в меня, а я не могу ни стрелять, ни видеть его
Исчезнет ли эта проблема, если мы перепишем алгоритм округления, чтобы он был менее либеральный за счет более уместного округления? Нет! Мы по-прежнему столкнемся с проблемой симметрии в комнате, полной колонн. Давайте сопоставим оба алгоритма «округления вниз» и «округления к нижнему входу в столбец», расположив их рядом для сравнения. Щелкните на элементе игры и поиграйте в «стереорежиме»:
Заметьте, как в обеих реализациях можно занять позицию, в которой вы сможете видеть за колонной монстра, но монстр, стоящий там, не сможет видеть вас:
Монстры, находящиеся в ячейках, отмеченных синими стрелками, видимы для игрока, но не могут сами его видеть. Монстры, стоящие в положениях, отмеченных оранжевыми стрелками, могут видеть игрока, но невидимы для него.
Проблема связана с тем, что алгоритм вычисляет набор таких ячеек, в которых любая точка видима из центра ячейки игрока. Чтобы алгоритм стал симметричным, нужно допустить, чтобы любая точка в целевой ячейке была видима из любой точки ячейки игрока. Это алгоритм «либерального поля зрения». Он использует те же концепции, которые мы обсуждали здесь; он постепенно сканирует область (квадрант, а не октант) и сохраняет набор сегментов линий (не векторов, так как не требуется, чтобы они выходили из начала), которые хранят области, находящиеся в поле зрения, по мере того, как вы удаляетесь дальше и дальше от начала. Это довольно хитроумный алгоритм, чтобы понять его правильно, поэтому я не буду описывать его здесь.
В следующий раз: Теперь, когда мы знаем, как вычислять верхние и нижние ячейки, путь к действительно работающему алгоритму довольно прямолинеен. Мы двинемся через детали кодирования.