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

Работа с графикой в Phaser — это мощный инструмент для создания динамических визуальных эффектов, интерфейсов и уникальных игровых объектов без использования внешних изображений. В этом примере мы разберём, как с помощью встроенного объекта `Graphics` нарисовать многоугольные звёзды с любым количеством лучей, задавая их размер, цвет и обводку. Этот подход полезен для генерации фонов, частиц, индикаторов или любых элементов, параметры которых могут меняться во время игры.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    create ()
    {

        const graphics = this.add.graphics();

        this.drawStar(graphics, 100, 300, 4, 50, 50 / 2, 0xffff00, 0xff0000);
        this.drawStar(graphics, 400, 300, 5, 100, 100 / 2, 0xffff00, 0xff0000);
        this.drawStar(graphics, 700, 300, 6, 50, 50 / 2, 0xffff00, 0xff0000);
    }

    drawStar (graphics, cx, cy, spikes, outerRadius, innerRadius, color, lineColor)
    {
        let rot = Math.PI / 2 * 3;
        let x = cx;
        let y = cy;
        const step = Math.PI / spikes;

        graphics.lineStyle(4, lineColor, 1);
        graphics.fillStyle(color, 1);
        graphics.beginPath();
        graphics.moveTo(cx, cy - outerRadius);

        for (let i = 0; i < spikes; i++)
        {
            x = cx + Math.cos(rot) * outerRadius;
            y = cy + Math.sin(rot) * outerRadius;
            graphics.lineTo(x, y);
            rot += step;

            x = cx + Math.cos(rot) * innerRadius;
            y = cy + Math.sin(rot) * innerRadius;
            graphics.lineTo(x, y);
            rot += step;
        }

        graphics.lineTo(cx, cy - outerRadius);
        graphics.closePath();
        graphics.fillPath();
        graphics.strokePath();
    }
}

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

const game = new Phaser.Game(config);

Создание графического контекста

Всё начинается с создания объекта Graphics, который является холстом для векторного рисования. Он добавляется в сцену через this.add.graphics(). Этот объект будет хранить все наши последующие команды рисования.

const graphics = this.add.graphics();

Анатомия функции drawStar

Функция drawStar — это сердце примера. Она принимает множество параметров, что даёт полную гибкость: - cx, cy — координаты центра звезды. - spikes — количество лучей (вершин). - outerRadius — радиус до внешних вершин. - innerRadius — радиус до внутренних впадин. - color — цвет заливки (в формате 0xRRGGBB). - lineColor — цвет обводки.

drawStar(graphics, cx, cy, spikes, outerRadius, innerRadius, color, lineColor)

Математика построения звезды

Звезда рисуется как замкнутый путь, состоящий из чередования внешних и внутренних вершин. Ключевой элемент — угол rot, который изначально повёрнут на 90 градусов вверх (в радианах это Math.PI / 2 * 3). На каждом шаге цикла rot увеличивается на угол step, который равен Math.PI / spikes. Это делит полный круг (π радиан — это половина круга, но из-за начального поворота и двойного шага на луч алгоритм работает корректно) на необходимое количество сегментов.

let rot = Math.PI / 2 * 3;
const step = Math.PI / spikes;

Процесс рисования пути

Перед началом рисования задаются стили линии и заливки с помощью graphics.lineStyle() и graphics.fillStyle(). Затем начинается путь (beginPath()), и первая точка ставится на верхнюю внешнюю вершину. В цикле для каждого луча вычисляются координаты внешней вершины, затем внутренней, и к ним рисуются линии (lineTo). После цикла путь замыкается, и применяются заливка и обводка.

graphics.lineStyle(4, lineColor, 1);
graphics.fillStyle(color, 1);
graphics.beginPath();
graphics.moveTo(cx, cy - outerRadius);
// ... цикл рисования вершин
graphics.closePath();
graphics.fillPath();
graphics.strokePath();

Вызов функции и результат

В методе create функция вызывается трижды с разными параметрами, создавая три различные звезды: с 4, 5 и 6 лучами. Это демонстрирует, как одна универсальная функция может генерировать разнообразные формы.

this.drawStar(graphics, 100, 300, 4, 50, 50 / 2, 0xffff00, 0xff0000);
this.drawStar(graphics, 400, 300, 5, 100, 100 / 2, 0xffff00, 0xff0000);
this.drawStar(graphics, 700, 300, 6, 50, 50 / 2, 0xffff00, 0xff0000);

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

Используя объект Graphics и немного тригонометрии, вы получаете полный контроль над созданием векторных фигур прямо во время выполнения игры. Для экспериментов попробуйте: анимировать параметры (например, пульсирующий innerRadius), менять цвет звезды в зависимости от игровых событий, использовать звёзды как частицы в системе или генерировать целые созвездия со случайным количеством лучей и размером.