О чем этот пример
Визуализация — ключевая часть любой игры. Иногда стандартных спрайтов недостаточно, и нужны динамически создаваемые фигуры. В Phaser для этого есть мощный объект `Graphics`, позволяющий рисовать примитивы прямо во время выполнения. В этой статье мы разберем, как с его помощью создавать дуги и секторы — базовые элементы для индикаторов здоровья, радиолокационных экранов или нестандартных эффектов. Мы начнем с простого примера, который рисует два закрашенных сегмента дуги, и подробно изучим каждый параметр метода `arc()`. Вы поймете, как контролировать форму, направление и сглаживание дуг, чтобы использовать их в своих проектах.
Версия 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('metal', 'assets/textures/alien-metal.jpg');
this.load.image('bunny', 'assets/sprites/bunny.png');
}
create ()
{
const graphics = this.add.graphics();
graphics.fillStyle(0x00ff00, 1);
graphics.beginPath();
graphics.arc(200, 300, 100, Phaser.Math.DegToRad(0), Phaser.Math.DegToRad(280), false, 0.01);
graphics.fillPath();
graphics.closePath();
graphics.beginPath();
graphics.arc(400, 300, 100, Phaser.Math.DegToRad(0), Phaser.Math.DegToRad(280), true, 0.01);
graphics.fillPath();
graphics.closePath();
}
}
const config = {
width: 800,
height: 600,
type: Phaser.WEBGL,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и создание графического объекта
Перед тем как рисовать, нужно подготовить сцену и создать холст для рисования — объект Graphics. В нашем примере загрузка ассетов в preload() не влияет на рисование дуг, она добавлена для демонстрации общего контекста.
Ключевой шаг происходит в методе create(), где создается графический объект. Именно он будет хранить все инструкции для отрисовки.
const graphics = this.add.graphics();
Сразу после создания мы задаем цвет заливки с помощью fillStyle(). Первый параметр — цвет в HEX-формате (0x00ff00 — зеленый), второй — альфа-канал (прозрачность от 0 до 1).
graphics.fillStyle(0x00ff00, 1);
Анатомия метода arc(): от углов до сглаживания
Метод arc() объекта Graphics — это основной инструмент для рисования дуг. Его сигнатура содержит несколько важных параметров, которые определяют результат.
graphics.arc(x, y, radius, startAngle, endAngle, anticlockwise, overshoot);
Разберем их по порядку:
* `x,y` — координаты центра дуги на холсте.
* radius — радиус дуги в пикселях.
* startAngle, endAngle — начальный и конечный угол дуги в радианах. Именно здесь в игру входит полезный хелпер Phaser.Math.DegToRad(), который переводит привычные градусы в радианы. Например, 280 градусов превращаются в нужное для API число.
* anticlockwise — логический параметр. Если false (по умолчанию), дуга рисуется по часовой стрелке от начального угла к конечному. Если true — против часовой стрелки.
* overshoot — параметр сглаживания (антиалиасинга) для контура дуги. Меньшее значение (например, 0.01) дает более гладкую, но ресурсоемкую кривую.
Рисование пути: beginPath, fillPath и closePath
В Phaser, как и в стандартном Canvas API, рисование выполняется с помощью концепции путей (paths). Последовательность команд строгая.
1. beginPath() — объявляет начало нового контура. Все последующие команды рисования (как arc()) будут относиться к этому пути.
2. Далее вызывается arc() с нужными параметрами, чтобы описать форму.
3. fillPath() — ключевая команда, которая заливает текущий описанный путь установленным ранее цветом (fillStyle). Без этого вызова дуга будет описана, но не видна на экране.
4. closePath() — формально завершает путь. Важно отметить, что для залитой фигуры эта команда не соединяет начальную и конечную точки линией (так как заливка и так сплошная), но является хорошей практикой для чистоты кода.
Вот как выглядит полный цикл для первой дуги:
graphics.beginPath();
graphics.arc(200, 300, 100, Phaser.Math.DegToRad(0), Phaser.Math.DegToRad(280), false, 0.01);
graphics.fillPath();
graphics.closePath();
Сравнение: дуга по часовой стрелке и против
В примере рисуются две дуги с одинаковыми центрами, радиусами и углами (от 0 до 280 градусов), но с разными значениями параметра anticlockwise. Это наглядно демонстрирует его влияние.
Первая дуга рисуется с anticlockwise: false. Дуга начинается на "3 часа" (0 радиан) и идет по часовой стрелке, останавливаясь чуть раньше полного круга. Получается закрашенный сегмент, похожий на недорисованный круг.
// Дуга по часовой стрелке (неполный круг снизу)
graphics.arc(200, 300, 100, Phaser.Math.DegToRad(0), Phaser.Math.DegToRad(280), false, 0.01);
Вторая дуга, с anticlockwise: true, начинает движение из той же точки, но против часовой стрелки. Чтобы достичь того же конечного угла (280 градусов), ей приходится пройти почти весь круг в обратном направлении. Визуально это создает гораздо больший закрашенный сегмент.
// Дуга против часовой стрелки (большой сегмент сверху)
graphics.arc(400, 300, 100, Phaser.Math.DegToRad(0), Phaser.Math.DegToRad(280), true, 0.01);
Этот прием полезен для создания индикаторов обратного отсчета или заполнения, где направление имеет значение.
Что попробовать дальше
Объект Graphics и метод arc() открывают прямой путь к созданию динамической векторной графики в Phaser. Вы научились описывать дуги, контролируя их размер, угол и направление обхода.
Для экспериментов попробуйте:
1. Анимировать параметр endAngle, чтобы создать плавно заполняющийся круговой индикатор.
2. Комбинировать несколько дуг с разными цветами (fillStyle) в одном Graphics объекте для создания сложных диаграмм.
3. Использовать lineStyle() перед beginPath() и strokePath() вместо fillPath(), чтобы нарисовать только контур дуги для других визуальных задач.
