Как перенести изометрический объект с одной плитки на другую, не перекрывая другие плитки

Я создал изометрическую среду на Javascript и HTML5 (2D Canvas), которая в основном работает нормально. Проблема, с которой я столкнулся, связана с наличием плиток разной высоты и последующей сортировкой индексов объектов на плитках (в данном случае при перемещении между двумя плитками бок о бок).

Например, один объект может находиться за плиткой перед ним, потому что высота плитки, на которой он находится, равна -1. Решение, которое я придумал, заключалось в том, чтобы рисовать каждый объект плитки сразу после рисования плитки, начиная с 0,0 и оттягивая оттуда каждую строку и столбец.

Это хорошо работает до тех пор, пока мне не понадобится переместить объект между двумя плитками. На этом этапе либо объект должен использовать промежуточную плитку (это реализовано на изображениях ниже), либо плитка будет перекрывать объект, поскольку плитка рисуется после объекта. Использование промежуточного тайла также создает проблему, когда объект ограждения в той же «строке» перерисовывается, потому что куб использует гораздо более высокий z-index из тайла 1,3 (это немного видно на изображении 1).

http://i.stack.imgur.com/PQJ0H.png

http://i.stack.imgur.com/DupM7.png

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

Итак, мой вопрос: при рисовании всей среды сверху вниз (или любым другим способом, если это позволяет), рисовании каждой плитки и ее объектов по очереди, есть ли умный способ отложить рисование объекта или создать массив объектов, которые нужно рисовать в правильном порядке? Кто-нибудь еще сталкивался с подобными проблемами и нашел ли кто-нибудь решения для этого?

Вся помощь очень ценится.

Пример моего тайлового кода:

// each column
for(y=0; y<totalColumns; y++){
    // each row
    for(x=0; x<totalRows; x++){
        tile = tiles[y][x];
        // draw tile
        drawTile(tile);
        objects = objects[y][x];
        // draw objects for that tile
        drawObjects(objects);
    }
}

Редактировать:

Одно из решений, которое я придумал (после прочтения вопроса самому себе), - это перебрать все плитки, получить массив высот плиток, отсортировать их, а затем выполнить традиционный рисунок. Вот так:

var layers = [];

for(var y=0; y<cols; y++){
    for(var x=0; x<rows; x++){
        tile = tiles[y][x];
        if(!layers.indexOf(tile.height)) layers.push(tile.height);
    }
}

// sort layers
layers.sort(/*function here to sort layers*/);

for(l=0; l<layers.length; l++){
    // draw tiles for this layer

    // draw objects for this layer

}

Возможны ли другие решения?


person Stephen Hamilton    schedule 03.12.2012    source источник
comment
Вы решили свою проблему. Высота / Z-значение - это обычный способ определения порядка рисования. Поскольку порядок рисования холста HTML5 является точным порядком выполнения кода, вам придется отсортировать порядок рисования самостоятельно.   -  person Karis    schedule 04.12.2012


Ответы (1)


Вы делаете правильные вещи в своем решении. Вы хотите сделать это для всего, что не имеет альфы.

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

person Adam William Larson    schedule 20.06.2014