О чем этот пример
При создании 2D-изометрических игр или проектов с кастомной графикой порядок, в котором тайлы отрисовываются на экране, критически важен для корректного отображения. Неправильный порядок может привести к визуальным артефактам, когда одни объекты неожиданно перекрывают другие. Этот пример демонстрирует, как использовать мощный, но часто упускаемый из виду метод `setRenderOrder()` для полного контроля над рендерингом тайловых слоёв, обеспечивая безупречный визуальный результат.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('tileset', 'assets/tilemaps/tiles/tileorder.png');
this.load.tilemapTiledJSON('map', 'assets/tilemaps/maps/tileorder.json');
}
create ()
{
this.cameras.main.scrollX = 120;
this.cameras.main.scrollY = 80;
this.cameras.main.zoom = 2;
const map = this.make.tilemap({ key: 'map' });
const tiles = map.addTilesetImage('tileset', 'tileset');
const layer1 = map.createLayer('floor', tiles, 0, 0);
const layer2 = map.createLayer('objects', tiles, 0, 0);
let renderOrder = 1;
const text = this.add.text(340, 250, 'Render Order: left-down');
this.input.on('pointerup', () =>
{
renderOrder++;
if (renderOrder === 4)
{
renderOrder = 0;
}
layer1.setRenderOrder(renderOrder);
layer2.setRenderOrder(renderOrder);
const orders = [
'right-down',
'left-down',
'right-up',
'left-up'
];
text.setText(`Render Order: ${orders[renderOrder]}`);
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#bfbfbf',
parent: 'phaser-example',
pixelArt: true,
scene: Example
};
const game = new Phaser.Game(config);
Суть проблемы рендеринга
По умолчанию Phaser отрисовывает тайлы на слое в порядке «слева-направо, сверху-вниз» (left-down). Этот порядок идеален для стандартных видов сверху или сбоку. Однако для изометрических проектов или определённых художественных стилей такой порядок может привести к тому, что задние объекты будут отрисованы поверх передних, ломая восприятие глубины.
Метод setRenderOrder() класса TilemapLayer позволяет переопределить этот алгоритм. Мы управляем последовательностью, в которой рендерер «обходит» тайлы на слое, прежде чем отправить их на отрисовку.
Настройка сцены и загрузка карты
Код начинается с базовой настройки. Обратите внимание на использование pixelArt: true в конфигурации игры — это предотвращает размытие пиксельной графики.
В методе preload() загружаются два ключевых ресурса: изображение тайлсета и файл карты в формате JSON, экспортированный из Tiled.
В create() мы сразу настраиваем камеру: сдвигаем её и увеличиваем зум, чтобы лучше видеть демонстрационный эффект. Затем создаём объект тайловой карты и добавляем к ней загруженный тайлсет.
// Настройка камеры для удобного просмотра
this.cameras.main.scrollX = 120;
this.cameras.main.scrollY = 80;
this.cameras.main.zoom = 2;
// Создание карты и тайлсета
const map = this.make.tilemap({ key: 'map' });
const tiles = map.addTilesetImage('tileset', 'tileset');
Создание слоёв и управление порядком
Из карты создаются два слоя: «floor» (пол) и «objects» (объекты). Изначально они отрисовываются в порядке, заданном в редакторе Tiled и по умолчанию в Phaser.
Ключевой элемент примера — переменная renderOrder и обработчик клика мыши. При каждом клике значение renderOrder увеличивается, а по достижении максимума сбрасывается на ноль. Это значение передаётся в метод setRenderOrder() для обоих слоёв.
const layer1 = map.createLayer('floor', tiles, 0, 0);
const layer2 = map.createLayer('objects', tiles, 0, 0);
let renderOrder = 1;
// Применение нового порядка отрисовки к слоям
layer1.setRenderOrder(renderOrder);
layer2.setRenderOrder(renderOrder);
Четыре режима отрисовки
Phaser предоставляет четыре предустановленных алгоритма порядка рендеринга, соответствующие индексам от 0 до 3. В коде они сопоставлены с понятными названиями в массиве orders. Метод setRenderOrder() принимает именно этот числовой индекс.
* **0 — right-down:** Отрисовка по строкам, слева-направо, сверху-вниз (стандартный для многих систем). * **1 — left-down:** Отрисовка по строкам, справа-налево, сверху-вниз (дефолтный в Phaser). * **2 — right-up:** Отрисовка по строкам, слева-направо, снизу-вверх. * **3 — left-up:** Отрисовка по строкам, справа-налево, снизу-вверх.
Изменение этого параметра мгновенно перестраивает порядок отрисовки всех тайлов на слое без необходимости перезаписывать саму карту.
const orders = [
'right-down',
'left-down',
'right-up',
'left-up'
];
text.setText(`Render Order: ${orders[renderOrder]}`);
Что попробовать дальше
Метод setRenderOrder() — это точный инструмент для решения специфических визуальных проблем в тайловых играх. Он незаменим для изометрии, кастомных перспектив или сложных декораций, где важен контроль над глубиной. Попробуйте применить его в своих проектах: создайте слой с деревьями и зданиями и поэкспериментируйте с порядком, чтобы добиться идеального перекрытия спрайтов игрока. Можно даже написать кастомную функцию сортировки, если стандартных четырёх режимов окажется недостаточно для вашей художественной задумки.
