Обновление: исправлен алгоритм рендеринга карты, добавлено больше иллюстраций, изменено форматирование.
Возможно, преимущество техники зигзага для отображения плиток на экране можно сказать, что плитки x
и y
координаты находятся на вертикальной и горизонтальной осях.
Подход "Рисование в бриллианте":
Рисуя изометрическую карту, используя «рисование ромбом», что, как я полагаю, относится только к визуализации карты с использованием вложенной for
-loop над двумерным массивом, как, например, в этом примере:
tile_map[][] = [[...],...]
for (cellY = 0; cellY < tile_map.size; cellY++):
for (cellX = 0; cellX < tile_map[cellY].size cellX++):
draw(
tile_map[cellX][cellY],
screenX = (cellX * tile_width / 2) + (cellY * tile_width / 2)
screenY = (cellY * tile_height / 2) - (cellX * tile_height / 2)
)
Преимущество:
Преимущество этого подхода заключается в том, что он представляет собой простой вложенный for
цикл с довольно простой логикой, который работает согласованно на всех тайлах.
Недостаток:
Один недостаток этого подхода заключается в том, что x
и y
координаты плитки на карте будет увеличиваться в диагональных линий, которые могли бы сделать его более трудно визуально отобразить расположение на экране на карте , представленной в виде массива:
Однако в реализации приведенного выше примера кода будет ловушка - порядок рендеринга приведет к тому, что плитки, которые должны находиться за определенными плитками, будут отображаться поверх плиток впереди:
Чтобы исправить эту проблему, for
порядок внутреннего цикла должен быть обратным - начиная с самого высокого значения и рендеринг к более низкому значению:
tile_map[][] = [[...],...]
for (i = 0; i < tile_map.size; i++):
for (j = tile_map[i].size; j >= 0; j--): // Changed loop condition here.
draw(
tile_map[i][j],
x = (j * tile_width / 2) + (i * tile_width / 2)
y = (i * tile_height / 2) - (j * tile_height / 2)
)
С помощью вышеуказанного исправления рендеринг карты должен быть исправлен:
Подход "зигзаг":
Преимущество:
Возможно, преимущество подхода «зигзаг» в том, что визуализированная карта может показаться немного более вертикально компактной, чем «алмазный» подход:
Недостаток:
Из-за попытки реализовать метод зигзага, недостатком может быть то, что немного сложнее написать код рендеринга, потому что он не может быть написан так просто, как вложенный for
-loop для каждого элемента в массиве:
tile_map[][] = [[...],...]
for (i = 0; i < tile_map.size; i++):
if i is odd:
offset_x = tile_width / 2
else:
offset_x = 0
for (j = 0; j < tile_map[i].size; j++):
draw(
tile_map[i][j],
x = (j * tile_width) + offset_x,
y = i * tile_height / 2
)
Кроме того, может быть немного трудно попытаться выяснить координату тайла из-за смещенного характера порядка рендеринга:
Примечание. Иллюстрации, включенные в этот ответ, были созданы с использованием Java-реализации представленного кода рендеринга плитки со следующим int
массивом в качестве карты:
tileMap = new int[][] {
{0, 1, 2, 3},
{3, 2, 1, 0},
{0, 0, 1, 1},
{2, 2, 3, 3}
};
Изображения плитки:
tileImage[0] ->
Коробка с коробкой внутри.
tileImage[1] ->
Черный ящик.
tileImage[2] ->
Белая коробка.
tileImage[3] ->
Коробка с высоким серым предметом внутри.
Примечание по ширине и высоте плитки
Переменные tile_width
и tile_height
которые используются в приведенных выше примерах кода относится к ширине и высоте плитки в первом изображении , представляющее плитку:
Использование размеров изображения будет работать, если совпадают размеры изображения и размеры плитки. В противном случае карта тайлов может быть визуализирована с промежутками между тайлами.
j = (2 * x - 4 * y) / tilewidth * 0.5; i = (p.x * 2 / tilewidth) - j;
.В любом случае, работа будет выполнена. Я предполагаю, что под зигзагом вы подразумеваете что-то вроде этого: (числа - это порядок рендеринга)
И под алмазом вы имеете в виду:
Первый метод требует больше рендеринга тайлов, чтобы рисовать весь экран, но вы можете легко выполнить проверку границ и пропустить любые тайлы полностью за пределами экрана. Оба метода потребуют некоторого сокращения чисел, чтобы выяснить, где находится фрагмент 01. В конце оба метода примерно одинаковы с точки зрения математики, необходимой для определенного уровня эффективности.
источник
Если у вас есть несколько плиток, которые превышают границы вашего бриллианта, я рекомендую рисовать в порядке глубины:
источник
Ответ Coobird правильный, полный. Тем не менее, я объединил его подсказки с подсказками с другого сайта, чтобы создать код, который работает в моем приложении (iOS / Objective-C), которым я хотел поделиться с любым, кто приходит сюда, ища такую вещь. Пожалуйста, если вам нравится / проголосуйте за этот ответ, сделайте то же самое для оригиналов; все, что я делал, было «стоять на плечах гигантов».
Что касается порядка сортировки, моя техника представляет собой модифицированный алгоритм художника: каждый объект имеет (а) высоту основания (я называю «уровень») и (б) X / Y для «основания» или «ноги» изображение (примеры: основание аватара у его ног; основание дерева у его корней; основание самолета - центральное изображение и т. д.) Затем я просто сортирую от самого низкого до самого высокого уровня, затем от самого низкого (самое высокое на экране) до самого высокого основания. Y, затем низший (самый левый) к высшему основанию-X. Это делает плитки так, как можно было бы ожидать.
Код для преобразования экрана (точки) в плитку (ячейку) и обратно:
источник
Вы можете использовать евклидово расстояние от самой высокой и ближайшей к зрителю точки, за исключением того, что это не совсем верно. Это приводит к сферическому порядку сортировки. Вы можете исправить это, посмотрев издалека. Еще дальше кривизна становится сглаженной. Так что просто добавьте скажем 1000 к каждому из компонентов x, y и z, чтобы получить x ', y' и z '. Сортировка по x '* x' + y '* y' + z '* z'.
источник
Реальная проблема заключается в том, что вам нужно нарисовать несколько плиток / спрайтов, пересекающих / охватывающих две или более других плиток.
После 2 (тяжелых) месяцев личного анализа проблемы я наконец нашел и реализовал «правильный чертеж рендеринга» для моей новой игры cocos2d-js. Решение состоит в том, чтобы отобразить для каждой плитки (восприимчивой), какие спрайты "спереди, сзади, сверху и сзади". Сделав это, вы можете нарисовать их, следуя «рекурсивной логике».
источник