изометрический порядок рисования с изображениями, превышающими одну плитку - алгоритм порядка рисования?

8

У меня есть изометрическая карта, на которой я размещаю различные изображения. Большинство изображений помещается на одной плитке, но некоторые изображения немного больше. Например, у меня есть кровать размером 2х3 плитки.

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

Два известных мне решения - это либо разделить изображение на сегменты мозаики 1x1, либо реализовать собственный алгоритм порядка рисования, например, назначив каждому изображению номер. Сначала рисуется изображение с номером 1, затем 2, 3 и т. Д.

У кого-нибудь есть совет, что мне делать?

Мне кажется, что разделение изометрического изображения очень неочевидно. Как вы решаете, какие части изображения «в» конкретной плитке? Я не могу позволить себе разделить все мои изображения вручную.

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

Роджер Смит
источник

Ответы:

3

То, что вам нужно, называется алгоритм художника.

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

Затем нарисуйте следующий ближайший и повторите до конца.

Ваши объекты, которые охватывают более одного тайла, должны иметь объявленную точку привязки / начала координат. Это ячейка сетки, которая при рисовании приведет к тому, что ваш более крупный объект также будет нарисован. Исходная точка выбирается так, чтобы она рисовалась после того, как все ячейки, в которые кровоточит объект, нарисованы первыми.

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

Пример кода для квадратной сетки. Измените направление петли для вашей алмазной сетки.

for(int y = 0; y < GridHeight; ++y) {
    for(int x = GridWidth - 1; x > -1; --x) {
        MapCell cell = getMapCell(x,y);
        DrawTerrain(cell);
        if(cell.IsDoodadOrigin){
            DrawDoodad(cell);
        }
        if(cell.IsCharacterOrigin){
            DrawCharacter(cell);
        }
    }
}
Джим
источник
Я не вижу, как это может работать? Представьте себе кровать 2х3, полностью окруженную ящиками. Итерируя по ячейкам, к тому времени, когда вы достигнете «источника» более крупного объекта, вы уже нарисовали прямоугольники, которые должны быть позади и перед кроватью.
Wozza
Вы правы, эта техника будет работать для квадратных сеток. Это также будет работать для диагональных сеток, которые используют квадратные символы / символы. Это не будет работать для неправильной формы 2x3 на диагональной сетке.
Джим
3

Разделите ваши объекты на кубы 1 × 1 × 1, назначив каждому кубу изображение частей объекта, которые физически находятся в этом кубе.

Это легко, если вы начинаете с реальных 3D-объектов и переводите их в 2D. Если вы рисуете свои объекты непосредственно в 2D (или если у вас есть существующий рисунок, который вам нужно разделить), это потребует некоторых ручных усилий. К счастью, разделение не обязательно должно быть точным, если вы убедитесь, что ни одна из частей изображения, назначенных данному кубу, не вышла за пределы гексагональной области, которую мог бы покрыть сплошной куб 1 × 1 × 1 в этой позиции. Это может помочь создать наложение, отображающее контуры каждого куба в качестве дополнительного слоя в графическом редакторе.

Затем вы просто назначаете приоритет каждому кубу как p = x + y + z (при условии, что все три координаты увеличиваются в направлении камеры) и визуализируете кубы в порядке возрастания по приоритету.


Вот краткий пример, основанный на этом изображении из Wikimedia Commons ( Phasmatinox / Allefant , используется по лицензии CC-By-SA 3.0 ):

        Изометрическая проекция протяженного объекта, разделенного на кубики

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

Обратите внимание, что вам, возможно, потребуется уточнить этот простой алгоритм, если у вас может быть несколько объектов в одной плитке, стены / этажи между плитками или объекты (например, люди), плавно перемещающиеся между плитками. Стены и полы довольно просты в обращении: их можно нарисовать в любой точке после содержимого плитки, перед которой они (с точки зрения камеры), и до плитки, за которой они находятся. Это также полезное правило для объектов, перемещающихся между плитками; относитесь к ним как к стене между этими плитками.

Что касается нескольких объектов в плитке, то иногда они довольно просты: например, если на картинке лежала книга, лежащая сверху сундука, ее, очевидно, следует рисовать после поверхности, на которой она лежит. Однако, все может стать более сложным, если у вас, скажем, есть предметы, на которых люди могут сидеть. Например, если человек сидел на скамейке лицом к камере, то тело человека должно быть вытянуто за скамейкой, но перед ним должны быть вытянуты ноги (которые находятся за скамейкой от камеры). Одним из решений в этом случае было бы разделить ноги сидящего человека на отдельный компонент со своей собственной позицией (либо в соседней плитке, либо между плитками).

Илмари Каронен
источник
1

Это может помочь вам разделить ваши объекты по типу или по высоте. Например, ландшафт (полы, стены) следует рисовать перед объектами (кроватями). Кроме того, изометрическая перспектива, плитки с более низкой высотой следует рисовать раньше, чем более высокие.

Кроме того, если вы используете нумерацию индекса (действительно Z-порядок), я рекомендую использовать пробелы между номерами - не делайте полы 1и постель 2. Используйте что-то вроде пола = 10и кровати = 20или 100что-то еще, чтобы вы могли «вставить» материал в середину, не увеличивая домино.

ashes999
источник
Я планирую делать то, что вы предлагаете в первом абзаце. Проблема, с которой я сталкиваюсь, заключается в том, что объекты похожего типа неправильно перекрываются. Например, моя кровать перекрывает прикроватный столик. Я предлагал, чтобы я давал каждому экземпляру изображения разное число, хотя, не давая всем кроватям номер 20, например?
Роджер Смит
Это зависит. Что делать, если у вас есть две кровати рядом? Один из способов, которым люди часто обходят это, - добавлять объекты в том порядке, в котором они должны быть нарисованы, но я не знаю, поможет ли это вам.
ashes999
1
Если две кровати расположены рядом друг с другом, то кровать с более высоким значением у следует рисовать выше другой. Если они имеют одинаковую координату y, то та, которая имеет наибольшее значение x (при условии, что вершина карты равна (0,0).
Роджер Смит