О чем этот пример
Работа с шестиугольными (гексагональными) картами открывает новые возможности для стратегических и пошаговых игр. Этот пример демонстрирует, как загрузить такую карту, создать на её основе слой и динамически добавлять новые тайлы во время выполнения игры. Вы научитесь манипулировать отдельными ячейками гексагональной сетки, что полезно для реализации механик строительства, изменения ландшафта или размещения юнитов.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
controls;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('tiles', 'assets/tilemaps/iso/tilesets/hexagonal-mini-6x.png');
this.load.tilemapTiledJSON('map', 'assets/tilemaps/iso/hexagonal-mini-6x.json');
}
create ()
{
const map = this.make.tilemap({ key: 'map' });
const tileset = map.addTilesetImage('hexmini-6x', 'tiles');
const platforms = map.createLayer('Ground', tileset);
const uiLayer = map.createBlankLayer('beep', tileset);
uiLayer.putTileAt(2, 2, 2);
uiLayer.putTileAt(2, 3, 2);
const cursors = this.input.keyboard.createCursorKeys();
this.cameras.main.setZoom(2);
this.cameras.main.centerOn(200, 100);
const controlConfig = {
camera: this.cameras.main,
left: cursors.left,
right: cursors.right,
up: cursors.up,
down: cursors.down,
acceleration: 0.02,
drag: 0.0005,
maxSpeed: 0.7
};
this.controls = new Phaser.Cameras.Controls.SmoothedKeyControl(controlConfig);
}
update (time, delta)
{
this.controls.update(delta);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
pixelArt: true,
scene: Example
};
const game = new Phaser.Game(config);
Загрузка ресурсов: карта и тайлсет
Для работы с шестиугольной картой нужны два ключевых ресурса: изображение тайлсета и файл карты в формате JSON, экспортированный из Tiled.
В методе preload() мы загружаем PNG-изображение, содержащее все графические тайлы, и JSON-файл, который описывает структуру слоёв карты и их заполнение. Обратите внимание на базовый URL — он указывает на публичный репозиторий с примерами Phaser.
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('tiles', 'assets/tilemaps/iso/tilesets/hexagonal-mini-6x.png');
this.load.tilemapTiledJSON('map', 'assets/tilemaps/iso/hexagonal-mini-6x.json');
Создание и отображение основного слоя карты
В методе create() происходит основная работа по инициализации карты. Сначала создаётся объект тайловой карты (Tilemap) по загруженному ключу. Затем из этой карты извлекается тайлсет по его имени внутри JSON-файла и связывается с загруженным изображением.
После этого создаётся слой Ground, который сразу отрисовывается на экране. Это статический фон нашей сцены.
const map = this.make.tilemap({ key: 'map' });
const tileset = map.addTilesetImage('hexmini-6x', 'tiles');
const platforms = map.createLayer('Ground', tileset);
Динамическое добавление тайлов на новый слой
Особенность этого примера — создание пустого динамического слоя поверх основного. Метод createBlankLayer() создаёт новый слой, связанный с тем же тайлсетом, но изначально не содержащий ни одного тайла.
На этом пустом слое uiLayer с помощью метода putTileAt() размещаются два тайла. Аргументы метода: индекс тайла в тайлсете (2), а также координаты X и Y в сетке карты. Это позволяет точечно изменять карту во время игры.
const uiLayer = map.createBlankLayer('beep', tileset);
uiLayer.putTileAt(2, 2, 2);
uiLayer.putTileAt(2, 3, 2);
Настройка камеры и управления
Чтобы лучше рассмотреть детали шестиугольной сетки, камера увеличивается (setZoom(2)) и смещается в определённую точку. Для удобства навигации по большой карте реализуется плавное управление камерой с клавиатуры с помощью SmoothedKeyControl. Этот контроллер обрабатывает нажатия стрелок, применяя ускорение и трение для создания инерции.
Конфигурация контроллера передаёт ссылки на клавиши и параметры физики движения камеры.
this.cameras.main.setZoom(2);
this.cameras.main.centerOn(200, 100);
const controlConfig = {
camera: this.cameras.main,
left: cursors.left,
right: cursors.right,
up: cursors.up,
down: cursors.down,
acceleration: 0.02,
drag: 0.0005,
maxSpeed: 0.7
};
this.controls = new Phaser.Cameras.Controls.SmoothedKeyControl(controlConfig);
Обновление состояния игры
В методе update() вызывается this.controls.update(delta). Это необходимо для того, чтобы обработчик управления камерой получал информацию о прошедшем времени (delta) и корректно рассчитывал её новую позицию с учётом инерции и нажатых клавиш. Без этого вызова камера не будет двигаться.
update (time, delta)
{
this.controls.update(delta);
}
Что попробовать дальше
Пример наглядно показывает базовый пайплайн работы с шестиугольными тайл-картами в Phaser: от загрузки до программного редактирования. Для экспериментов попробуйте изменить индекс тайла в putTileAt, чтобы класть другие элементы, или вызывайте этот метод по клику мыши для интерактивного редактирования карты. Можно также создать несколько динамических слоёв для разделения игровых сущностей (например, юнитов, построек и эффектов).
