Работа с сеткой: Grid и Snap

Phaser предоставляет гибкие инструменты для организации объектов в пространстве игры с использованием сетки. Сетка облегчает позиционирование, выравнивание и взаимодействие объектов, особенно в 2D-играх с тайловой графикой или структурированными уровнями. Основные концепции включают Grid и Snap, которые позволяют автоматизировать размещение объектов по фиксированным координатам.


Grid: создание и использование сетки

Сетка (Grid) в Phaser — это логическая структура, определяющая деление игрового пространства на равные ячейки. Она не обязательно визуальна, но служит базой для позиционирования объектов.

Инициализация сетки:

const gridSize = 32; // размер одной ячейки в пикселях
const cols = Math.floor(game.config.width / gridSize);
const rows = Math.floor(game.config.height / gridSize);

Здесь gridSize задаёт ширину и высоту ячейки. cols и rows определяют количество ячеек по горизонтали и вертикали, исходя из размеров канвы игры.

Вычисление позиции объекта по сетке:

function getGridPosition(col, row) {
    return {
        x: col * gridSize + gridSize / 2,
        y: row * gridSize + gridSize / 2
    };
}

const position = getGridPosition(5, 3);
player.setPosition(position.x, position.y);

Ключевой момент: координаты рассчитываются от центра ячейки для удобного выравнивания спрайтов.

Отображение сетки (опционально):

const graphics = this.add.graphics();
graphics.lineStyle(1, 0xffffff, 0.3);

for (let i = 0; i <= cols; i++) {
    graphics.moveTo(i * gridSize, 0);
    graphics.lineTo(i * gridSize, game.config.height);
}

for (let j = 0; j <= rows; j++) {
    graphics.moveTo(0, j * gridSize);
    graphics.lineTo(game.config.width, j * gridSize);
}

graphics.strokePath();

Отображение сетки полезно для отладки и визуальной привязки объектов, но в релизной версии можно скрывать графику.


Snap: привязка объектов к сетке

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

Пример использования Snap для спрайта:

this.input.on('pointerdown', (pointer) => {
    const snappedX = Math.round(pointer.x / gridSize) * gridSize;
    const snappedY = Math.round(pointer.y / gridSize) * gridSize;
    sprite.setPosition(snappedX + gridSize / 2, snappedY + gridSize / 2);
});

Ключевой момент: Math.round гарантирует, что объект займёт ближайшую ячейку. При необходимости можно использовать Math.floor или Math.ceil для смещения привязки.

Snap при перемещении объектов:

Phaser поддерживает гибкую привязку через интерактивность спрайтов:

sprite.setInteractive();
this.input.setDraggable(sprite);

this.input.on('drag', (pointer, obj, dragX, dragY) => {
    const snappedX = Math.round(dragX / gridSize) * gridSize;
    const snappedY = Math.round(dragY / gridSize) * gridSize;
    obj.setPosition(snappedX + gridSize / 2, snappedY + gridSize / 2);
});

Это позволяет создавать drag-and-drop с точной привязкой к сетке.


Комбинирование Grid и Snap для тайловых карт

Grid и Snap вместе идеально подходят для создания тайловых уровней. Каждое изменение координат объекта может быть автоматически округлено до ячейки, что упрощает обработку столкновений и логики игры.

Создание карты с привязкой:

const map = [];
for (let row = 0; row < rows; row++) {
    map[row] = [];
    for (let col = 0; col < cols; col++) {
        map[row][col] = null; // пустая ячейка
    }
}

Размещение объектов на карте:

function placeTile(tile, col, row) {
    const pos = getGridPosition(col, row);
    tile.setPosition(pos.x, pos.y);
    map[row][col] = tile;
}

Такой подход облегчает работу с игровым уровнем, позволяет проверять занятость ячеек и строить алгоритмы для ИИ или построения уровней.


Дополнительные возможности

  • Персонализированный Snap: можно задавать разные размеры ячеек по оси X и Y для прямоугольной сетки.
  • Сеточные смещения: добавление отступов между ячейками.
  • Сетка для GUI: Snap и Grid применимы не только для игровой области, но и для интерфейсов, где элементы выравниваются по ячейкам.

Grid и Snap в Phaser образуют фундамент для точного позиционирования объектов, упрощая создание уровней, систем столкновений и динамических интерактивных элементов. Они позволяют перейти от хаотичного размещения к структурированному и предсказуемому миру игры.