О чем этот пример
Создание динамических визуальных эффектов и сложных траекторий — обычная задача в разработке игр. Работая напрямую с геометрическими примитивами, вы получаете полный контроль над отрисовкой, что полезно для генерации фонов, путей следования или областей поражения. В этом примере мы разберем, как с помощью всего двух методов класса `Phaser.Geom.Line` — `Offset` и `Rotate` — можно генерировать изящные вращающиеся узоры, понимая базовые принципы трансформации линий.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
const line = new Phaser.Geom.Line(330, 150, 430, 170);
const graphics = this.add.graphics({ lineStyle: { width: 3, color: 0xaa00aa } });
graphics.strokeLineShape(line);
const angleStep = 1 / 15 * Phaser.Math.PI2;
for (let i = 0; i < 15; i++)
{
const angle = i * angleStep;
const xOffset = Math.cos(angle) * 50;
const yOffset = Math.sin(angle) * 50;
Phaser.Geom.Line.Rotate(line, angleStep);
Phaser.Geom.Line.Offset(line, xOffset, yOffset);
graphics.strokeLineShape(line);
}
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и создание базовой линии
Вся работа происходит в методе create основной сцены. Первым делом мы создаем исходный отрезок — фундамент для будущего узора. Затем инициализируем графический объект (Graphics), который будет отвечать за отрисовку всех линий на экране.
const line = new Phaser.Geom.Line(330, 150, 430, 170);
const graphics = this.add.graphics({ lineStyle: { width: 3, color: 0xaa00aa } });
graphics.strokeLineShape(line);
Код выше создает линию от точки (330, 150) до точки (430, 170) и сразу же отрисовывает ее фиолетовым цветом. Это наша отправная точка.
Математика цикла: угол и смещение
Для создания узора нам нужно повторить трансформацию линии несколько раз. Мы используем цикл на 15 итераций. Ключевой параметр — угловой шаг (angleStep), который определяет, на сколько радиан будет поворачиваться линия на каждом витке цикла. Смещение линии (xOffset, yOffset) рассчитывается через тригонометрические функции Math.cos и Math.sin, что позволяет двигать линию по круговой траектории.
const angleStep = 1 / 15 * Phaser.Math.PI2;
for (let i = 0; i < 15; i++) {
const angle = i * angleStep;
const xOffset = Math.cos(angle) * 50;
const yOffset = Math.sin(angle) * 50;
Здесь Phaser.Math.PI2 — это константа, равная 2 * PI (полный круг). Умножение на 50 задает радиус окружности, по которой будет "ходить" наша линия.
Двойная трансформация: поворот и смещение
На каждом шаге цикла мы последовательно применяем к нашей линии две операции. Важно, что эти методы (Rotate и Offset) изменяют координаты существующего объекта line, а не создают новую копию. Это называется мутацией объекта.
Phaser.Geom.Line.Rotate(line, angleStep);
Phaser.Geom.Line.Offset(line, xOffset, yOffset);
graphics.strokeLineShape(line);
Сначала Line.Rotate(line, angleStep) поворачивает линию вокруг ее центра на фиксированный угловой шаг. Затем Line.Offset(line, xOffset, yOffset) сдвигает уже повернутую линию по рассчитанным ранее координатам. После всех преобразований измененная линия сразу отрисовывается. Постепенное накопление изменений и создает финальный спиралевидный узор.
Конфигурация игры и запуск
Это стандартная конфигурация для примера на Phaser. Она задает размеры холста, автоматически выбирает рендерер (WebGL или Canvas) и указывает, какую сцену использовать в качестве основной.
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
После создания экземпляра игры new Phaser.Game(config) автоматически инициализируется сцена и вызывается ее метод create, запуская весь описанный выше процесс.
Что попробовать дальше
Комбинируя простые геометрические операции — поворот и смещение — можно генерировать сложные и визуально привлекательные паттерны. Этот подход лежит в основе создания процедурных траекторий для снарядов, орбит для планет или декоративных элементов интерфейса. Для экспериментов попробуйте изменить радиус смещения (число 50), количество итераций в цикле или добавьте изменение цвета линии на каждом шаге через graphics.lineStyle. Также интересно будет привязать смещение не к тригонометрическим функциям, а, например, к шуму Перлина, чтобы получить более органичные, несимметричные формы.
