О чем этот пример
Работа с двумерными массивами (матрицами) — частая задача в игровой разработке, будь то генерация уровней, карты тайлов или логические головоломки. Встроенные утилиты Phaser упрощают манипуляции с такими структурами данных. В этой статье мы разберем пример использования `Phaser.Utils.Array.Matrix.Translate()` для сдвига матрицы в любом направлении. Вы научитесь динамически изменять игровые данные по клику, что открывает возможности для создания интерактивных редакторов и механик, основанных на перемещении блоков данных.
Версия 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('arrow', 'assets/sprites/arrow.png');
}
create ()
{
this.add.text(10, 10, 'Click to arrows to translate the array matrix', { font: '16px Courier', fill: '#ffffff' });
const left = this.add.image(96, 384, 'arrow').setAngle(-180).setInteractive();
const right = this.add.image(1024 - 96, 384, 'arrow').setInteractive();
const up = this.add.image(512, 96, 'arrow').setAngle(-90).setInteractive();
const down = this.add.image(512, 768 - 96, 'arrow').setAngle(90).setInteractive();
const text = this.add.text(260, 200, '', { font: '32px Courier', fill: '#00ff00' });
let matrix = [
[ 1, 1, 1, 1, 1, 1, 1 ],
[ 4, 5, 5, 5, 5, 5, 2 ],
[ 4, 8, 8, 8, 8, 6, 2 ],
[ 4, 8, 9, 0, 9, 6, 2 ],
[ 4, 8, 9, 9, 9, 6, 2 ],
[ 4, 7, 7, 7, 7, 7, 2 ],
[ 3, 3, 3, 3, 3, 3, 3 ]
];
text.setText(Phaser.Utils.Array.Matrix.MatrixToString(matrix));
left.on('pointerup', () =>
{
matrix = Phaser.Utils.Array.Matrix.Translate(matrix, -1, 0);
text.setText(Phaser.Utils.Array.Matrix.MatrixToString(matrix));
});
right.on('pointerup', () =>
{
matrix = Phaser.Utils.Array.Matrix.Translate(matrix, 1, 0);
text.setText(Phaser.Utils.Array.Matrix.MatrixToString(matrix));
});
up.on('pointerup', () =>
{
matrix = Phaser.Utils.Array.Matrix.Translate(matrix, 0, -1);
text.setText(Phaser.Utils.Array.Matrix.MatrixToString(matrix));
});
down.on('pointerup', () =>
{
matrix = Phaser.Utils.Array.Matrix.Translate(matrix, 0, 1);
text.setText(Phaser.Utils.Array.Matrix.MatrixToString(matrix));
});
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и элементов управления
Класс Example расширяет Phaser.Scene. В методе preload загружается спрайт стрелки. В create создаются четыре интерактивных изображения стрелок, повернутых в разные стороны, которые будут служить кнопками управления.
Также создается текстовый объект text для отображения матрицы и инициализируется сама матрица matrix — двумерный массив чисел. Для удобного отображения используется функция Phaser.Utils.Array.Matrix.MatrixToString().
const left = this.add.image(96, 384, 'arrow').setAngle(-180).setInteractive();
const right = this.add.image(1024 - 96, 384, 'arrow').setInteractive();
const up = this.add.image(512, 96, 'arrow').setAngle(-90).setInteractive();
const down = this.add.image(512, 768 - 96, 'arrow').setAngle(90).setInteractive();
const text = this.add.text(260, 200, '', { font: '32px Courier', fill: '#00ff00' });
let matrix = [
[ 1, 1, 1, 1, 1, 1, 1 ],
[ 4, 5, 5, 5, 5, 5, 2 ],
[ 4, 8, 8, 8, 8, 6, 2 ],
[ 4, 8, 9, 0, 9, 6, 2 ],
[ 4, 8, 9, 9, 9, 6, 2 ],
[ 4, 7, 7, 7, 7, 7, 2 ],
[ 3, 3, 3, 3, 3, 3, 3 ]
];
text.setText(Phaser.Utils.Array.Matrix.MatrixToString(matrix));
Связывание событий с функцией Translate
Каждой стрелке назначается обработчик события 'pointerup'. Внутри обработчика вызывается ключевая функция Phaser.Utils.Array.Matrix.Translate(). Она принимает три аргумента:
1. Исходную матрицу.
2. Смещение по горизонтали (`x`).
3. Смещение по вертикали (`y`).
Функция возвращает **новую матрицу**, сдвинутую на указанное количество строк и столбцов. Элементы, выходящие за границы, "заворачиваются" с противоположной стороны (циклический сдвиг). Результат присваивается переменной matrix, а затем обновляется текст на экране.
left.on('pointerup', () => {
matrix = Phaser.Utils.Array.Matrix.Translate(matrix, -1, 0);
text.setText(Phaser.Utils.Array.Matrix.MatrixToString(matrix));
});
right.on('pointerup', () => {
matrix = Phaser.Utils.Array.Matrix.Translate(matrix, 1, 0);
text.setText(Phaser.Utils.Array.Matrix.MatrixToString(matrix));
});
Как работает Translate и его параметры
Функция Translate выполняет циклический сдвиг (rotation) матрицы. Это значит, что строки или столбцы, которые "выталкиваются" за пределы массива, не теряются, а появляются с другой стороны.
* Translate(matrix, 1, 0) сдвигает все столбцы вправо. Крайний правый столбец становится крайним левым.
* Translate(matrix, -1, 0) сдвигает все столбцы влево.
* Translate(matrix, 0, 1) сдвигает все строки вниз. Нижняя строка становится верхней.
* Translate(matrix, 0, -1) сдвигает все строки вверх.
Можно задавать смещение больше единицы: Translate(matrix, 2, -1) сдвинет матрицу на два столбца вправо и на одну строку вверх.
Важно понимать, что исходная матрица **не изменяется**. Функция всегда возвращает новый массив.
Практическое применение в играх
Эта техника полезна не только для отображения чисел. Представьте, что значения в матрице — это ID тайлов на карте уровня. Тогда Translate позволит реализовать:
* **Бесконечно прокручиваемую карту** (как в старых пошаговых стратегиях). * **Механику сдвигающих платформ или блоков** в головоломках (например, как в игре "Пятнашки"). * **Простой редактор уровней**, где вы можете "прокручивать" заготовленный фрагмент карты. * **Генерацию ландшафта** на лету, смещая и дополняя матрицу с данными.
Вместо чисел в матрице могут храниться объекты, описывающие состояние клетки игрового поля.
Что попробовать дальше
Утилита Phaser.Utils.Array.Matrix.Translate() — мощный и простой инструмент для работы с двумерными данными. Она избавляет от необходимости писать вложенные циклы для ручного сдвига массивов. Для экспериментов попробуйте:
1. Связать матрицу с сеткой спрайтов на сцене, чтобы визуализировать сдвиг графически.
2. Использовать не циклический сдвиг, а добавлять новые строки/столбцы с дефолтными значениями при выходе за границы.
3. Комбинировать Translate с другими функциями из Phaser.Utils.Array.Matrix, например, RotateMatrix для поворота данных.
