О чем этот пример

Работа с игровыми полями, картами уровней или системами сеток часто требует манипуляций с двумерными массивами. Поворот всей матрицы данных на 180 градусов — типичная задача при реализации зеркальных режимов, реверса уровня или алгоритмов procedural generation. Встроенный API Phaser позволяет сделать это одной строкой, избегая сложных циклов и ошибок индексов. Эта статья покажет, как использовать утилиты Phaser для эффективной работы с матрицами в вашей игре.

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


class Example extends Phaser.Scene
{
    create ()
    {
        this.add.text(10, 10, 'Click to rotate the array matrix 180', { font: '16px Courier', fill: '#ffffff' });

        const text = this.add.text(200, 200, '', { font: '32px Courier', fill: '#00ff00' });

        let matrix = [
            [ 1, 1, 1, 1, 1, 1 ],
            [ 2, 0, 0, 0, 0, 4 ],
            [ 2, 0, 1, 2, 0, 4 ],
            [ 2, 0, 3, 4, 0, 4 ],
            [ 2, 0, 0, 0, 0, 4 ],
            [ 3, 3, 3, 3, 3, 3 ]
        ];

        text.setText(Phaser.Utils.Array.Matrix.MatrixToString(matrix));

        this.input.on('pointerup', () =>
        {

            matrix = Phaser.Utils.Array.Matrix.Rotate180(matrix);

            text.setText(Phaser.Utils.Array.Matrix.MatrixToString(matrix));

        });
    }
}

const config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

Зачем вращать матрицу?

В игровой разработке двумерные массивы (матрицы) часто представляют собой данные уровня: расположение тайлов, препятствий, врагов или сокровищ. Поворот матрицы на 180 градусов создает зеркальную копию этих данных относительно центра.

Типичные применения: * Создание вариаций уровня без ручного дизайна. * Реализация механики "перевернутого мира". * Упрощение алгоритмов, работающих с симметричными структурами.

Ручная реализация через вложенные циклы возможна, но подвержена ошибкам. Phaser предлагает готовое, оптимизированное решение.

Анализ исходного кода

В примере создается простая сцена с текстовыми элементами. Ключевые моменты: * Матрица 6x6 инициализирована числами для наглядности. * Утилита Phaser.Utils.Array.Matrix.MatrixToString форматирует массив для красивого отображения в текстовом объекте. * Обработчик клика вызывает метод поворота и обновляет текст.

Давайте посмотрим на структуру примера:

class Example extends Phaser.Scene
{
    create ()
    {
        this.add.text(10, 10, 'Click to rotate...', { font: '16px Courier', fill: '#ffffff' });
        const text = this.add.text(200, 200, '', { font: '32px Courier', fill: '#00ff00' });

        let matrix = [
            [ 1, 1, 1, 1, 1, 1 ],
            [ 2, 0, 0, 0, 0, 4 ],
            [ 2, 0, 1, 2, 0, 4 ],
            [ 2, 0, 3, 4, 0, 4 ],
            [ 2, 0, 0, 0, 0, 4 ],
            [ 3, 3, 3, 3, 3, 3 ]
        ];
        text.setText(Phaser.Utils.Array.Matrix.MatrixToString(matrix));

Инициализация завершена. Матрица отображается. Далее идет логика интерактивности:

this.input.on('pointerup', () =>
        {
            matrix = Phaser.Utils.Array.Matrix.Rotate180(matrix);
            text.setText(Phaser.Utils.Array.Matrix.MatrixToString(matrix));
        });
    }
}

Каждый клик запускает операцию поворота и обновление интерфейса.

Ключевой API: Phaser.Utils.Array.Matrix

Phaser хранит матричные утилиты в пространстве имен Phaser.Utils.Array.Matrix. В примере используются два метода:

1. MatrixToString(matrix): принимает двумерный массив и возвращает строку, где строки матрицы разделены символом новой строки \n. Это удобно для вывода в текстовый объект Phaser.

2. Rotate180(matrix): единственный аргумент — исходная матрица. Метод возвращает **новый** массив, являющийся повернутой на 180 градусов копией исходного. Исходный массив не изменяется.

Важно: метод ожидает **правильную** матрицу — массив массивов одинаковой длины. Нерегулярные массивы могут привести к ошибкам.

От теории к практике: как применить в игре

Представьте, что ваша матрица — это слой тайлов уровня. Вот как можно интегрировать поворот в игровую логику.

// 1. Данные уровня (например, ID тайлов)
let levelMap = [
    [1, 1, 0, 0],
    [2, 3, 1, 0],
    [0, 2, 3, 1],
    [0, 0, 2, 3]
];

// 2. Создание уровня на основе матрицы
function createTileLayer(mapMatrix) {
    for (let y = 0; y < mapMatrix.length; y++) {
        for (let x = 0; x < mapMatrix[y].length; x++) {
            // this.add.image(x * 64, y * 64, 'tiles', mapMatrix[y][x]);
        }
    }
}

// 3. По триггеру (клик, кнопка) создаем перевернутый уровень
this.input.on('pointerup', () => {
    // Генерируем новую перевернутую карту
    let rotatedMap = Phaser.Utils.Array.Matrix.Rotate180(levelMap);
    // Очищаем старый слой и создаем новый
    createTileLayer(rotatedMap);
});

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

Что попробовать дальше

Утилита Phaser.Utils.Array.Matrix.Rotate180 — мощный, но простой инструмент для трансформации игровых данных. Она избавляет разработчика от написания шаблонного кода и позволяет сосредоточиться на геймдизайне. Идеи для экспериментов: 1. Комбинируйте Rotate180 с другими методами, например RotateRight или TransposeMatrix, для создания сложных вариаций. 2. Используйте поворот не для всего уровня, а для отдельных комнат или областей в процедурной генерации подземелий. 3. Примените к матрице, представляющей поле боя в пошаговой стратегии, для анализа симметричных позиций ИИ.