Лучшая техника для рисования изометрических плиток

8

Я думаю о создании простой изометрической игры с HTML5 Canvas и задаюсь вопросом, какой самый быстрый способ визуализации плиток.

Поскольку плитки имеют ромбовидную форму, но drawImage рисует прямоугольники, я должен пропустить углы (черные части ниже):

образец алмазной плитки

Я думаю, что это оставляет мне три варианта:

  1. Используйте объекты изображения с альфа-каналами (.png). Боюсь, это может убить производительность.
  2. Используйте обтравочный контур. Если визуализатор оптимизирован, это может быть довольно быстро.
  3. Предварительно представьте квадратные плитки, как это:

предварительно обработанные квадратные плитки

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

Какой лучший или самый быстрый способ сделать изометрические плитки? Что используют другие игры, такие как FarmVille?

JDM
источник
1
Я думаю, что «лучшая техника» загружена и будет зависеть от требований игры, используемой технологии и разработчика, создающего игру.
MichaelHouse
1
Какие проблемы у вас на самом деле? Кажется, вы дали три ответа на свой вопрос в тексте вопроса?
Тревор Пауэлл
1
Это не имеет достаточно голосов: ЛУЧШИЙ ЛУЧШИЙ BESSSSSSST! Argh?
Джимми
1
Полагаю, вы должны следовать совету, найденному здесь: meta.gamedev.stackexchange.com/a/638/7191
MichaelHouse
1
Так вы не знаете, что это на самом деле проблема с производительностью? Вы просто пытаетесь оптимизировать код перед его написанием? В таком случае -1 и голосование закрыто.
Тревор Пауэлл

Ответы:

11

Я рекомендую использовать прозрачность (альфа-канал).

Это означает, что когда вы хотите вертикальный объект на плитке, как это:

плитка с деревом

Тогда вы можете легко это сделать, если ваш рендерер рисует тайлы спереди назад, т.е. алгоритм рисования.

КРЕДИТ ИЗОБРАЖЕНИЯ: набор плиток Райнера.

MarkR
источник
9

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

Хакерский вариант для создания изометрического вида с минимальными усилиями состоит в том, чтобы фактически использовать ортогональные плитки и использовать context.transform, чтобы установить матрицу проекции, которая делает карту изометрической (или комбинацию context.rotate и context.scale, когда вы не не знаю, как работают проекционные матрицы).

Подробности смотрите в спецификации методов преобразования холста .

Плитка изображения:

базовое изображение плитки

Чертежный код:

    for (var x = 0; x < 5; x++) {
        for (var y = 0; y < 5; y++) {
            ctx.drawImage(img, x * img.width, y * img.height);
        }
    }

Результат перед применением матрицы:

без применения матрицы преобразования

Тот же код с тем же изображением плитки после применения этой матрицы преобразования:

    ctx.transform(  1,   0.5,
                   -1,   0.5,
                  160,   0    );

с матрицей преобразования

С штриховой сеткой удаляется из мозаичного изображения и изменить плитки смещения в коде рисования до img.width - 1и img.height - 1избавиться от пробелов , вызванных преобразованием. Внезапно плитка выглядит наполовину безобразно:

с матрицей и некоторыми настройками

Основным недостатком этого метода является то, что когда вы создаете свои плитки в графическом редакторе, они не будут такими, какими вы их видите. Вы также столкнетесь с проблемами, когда захотите нарисовать любые объекты, которые не находятся на полу, но стоят прямо. Для этого вы можете отключить матрицу преобразования, прежде чем рисовать их, но тогда вам придется рассчитать положение самостоятельно. Вы можете использовать эти формулы для этого:

var xScreen = xWorld * 1   + yWorld * -1  + 160;
var yScreen = xWorld * 0.5 + yWorld * 0.5 + 0;  

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

Так почему я должен это делать?

Этот метод хорош, когда вы:

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

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

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

Philipp
источник
Это, безусловно, возможно сделать. Таким образом, вы можете иметь «плоские» или «нисходящие» плитки. Однако это означает, что любые «3d» элементы в плитках не могут быть легко выполнены. Я предпочитаю делать это преобразование заранее.
MarkR
+1 если не только за экспертное объяснение! Отлично сработано.
Luceos
@MarkR: после того, как вы сделали свой комментарий, я значительно расширил свой ответ. Возможно, вы захотите взглянуть, применимо ли оно до сих пор.
Филипп
1
Спасибо за подробную статью! Это очень интересная техника, я не думал об этом раньше. Однако, поскольку я начинаю с нуля (и одинаково плохо рисую изометрические и квадратные плитки ;-)), я пойду за настоящие изометрические плитки. Кроме того, это, кажется, не очень быстро. Я сделал небольшой тест, и перетаскивание тайлов без матрицы преобразования в целочисленные позиции пикселей примерно в 3 раза быстрее, чем при преобразовании на моем ПК. Тем не менее, я мог бы использовать это для некоторых спецэффектов.
JDM
Есть ли способ добавить уровень z на эту карту?
Тарион
3
  1. Вы используете context.drawImage для копирования пиксельных данных из одного источника (изображения или холста за пределами экрана) в другой (за пределами экрана или холста на экране), который изящно обрабатывает альфу из коробки. Canvas с аппаратным ускорением, поэтому тестирование позволит вам определить, есть ли заметная разница в скоростях рендеринга по сравнению с непрозрачными пикселями.

  2. Отсечение потребует от вас нажатия / выталкивания состояния контекста при определении пути отсечения один раз для плитки, что может быть дорогостоящей операцией с учетом перерисовки изометрии.

  3. Предварительно обработанные плитки, как вы заявляете, потребуют огромного количества плиток «коннекторов», которые могут быть или не быть выполнимыми. (Я больше склоняюсь к "не может".)

Четвертое решение состоит в том, чтобы принять предварительно визуализированный «фрагмент» (PRC) фрагментов, сгенерированных один раз для закадровых полотен, а затем покрыть экран PRC один раз за кадр. Все равно будет перерасход, но построение PRC один раз и рендеринг со смещением, определяемым положением персонажа игрока (или камеры наблюдения) относительно PRC, должно быть относительно простой операцией. Это позволит вам комбинировать рендеринг с опцией # 1, которая является IMO лучшим вариантом, если производительность не учитывалась (поскольку ее проще всего реализовать).

SWS
источник
3

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

Прямоугольный узор под плиткой

AAAAAAAAAAAA
источник