О чем этот пример
Объект `Graphics` в Phaser — это мощный инструмент для рисования геометрических фигур и создания динамических визуальных эффектов прямо во время выполнения игры. В отличие от предзагруженных спрайтов, графика генерируется программно, что идеально подходит для интерфейсов, спецэффектов или интерактивных элементов, меняющих внешний вид по действиям игрока. В этой статье мы разберем практический пример создания интерактивного "кусочка пирога", который реагирует на наведение курсора, и покажем, как легко управлять его отрисовкой и взаимодействием.
Версия 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.spritesheet('aliens', 'assets/sprites/bsquadron-enemies.png', { frameWidth: 192, frameHeight: 160 });
}
create ()
{
const graphics = this.add.graphics();
graphics.fillStyle(0xffff00, 1);
graphics.slice(400, 300, 200, Phaser.Math.DegToRad(340), Phaser.Math.DegToRad(20), true);
graphics.fillPath();
graphics.setInteractive(new Phaser.Geom.Circle(400, 300, 200), Phaser.Geom.Circle.Contains);
graphics.on('pointerover', () =>
{
graphics.clear();
graphics.fillStyle(0xff0000, 1);
graphics.slice(400, 300, 200, Phaser.Math.DegToRad(340), Phaser.Math.DegToRad(20), true);
graphics.fillPath();
});
graphics.on('pointerout', () =>
{
graphics.clear();
graphics.fillStyle(0xffff00, 1);
graphics.slice(400, 300, 200, Phaser.Math.DegToRad(340), Phaser.Math.DegToRad(20), true);
graphics.fillPath();
});
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Создание и настройка объекта Graphics
В Phaser объект Graphics создается через фабричный метод сцены this.add.graphics(). Это ваш холст для рисования.
Перед началом рисования необходимо задать стиль заливки с помощью метода fillStyle(). Первый аргумент — цвет в шестнадцатеричном формате, второй — альфа-канал (прозрачность).
const graphics = this.add.graphics();
graphics.fillStyle(0xffff00, 1);
После настройки стиля можно приступать к определению формы. В нашем примере используется метод slice(), который рисует сектор круга (как кусок пирога или пиццы). Для его отображения на экране необходимо завершить команду вызовом fillPath().
Рисование фигуры: метод slice()
Метод slice() рисует сектор (срез) круга. Его параметры определяют положение, размер и углы.
graphics.slice(400, 300, 200, Phaser.Math.DegToRad(340), Phaser.Math.DegToRad(20), true);
graphics.fillPath();
Разберем аргументы по порядку:
1. **400, 300**: координаты X и Y центра круга.
2. **200**: радиус круга.
3. **Phaser.Math.DegToRad(340)**: начальный угол среза. Поскольку Phaser работает с радианами, мы используем вспомогательную функцию DegToRad() для конвертации 340 градусов.
4. **Phaser.Math.DegToRad(20)**: конечный угол среза (20 градусов). Фигура будет нарисована от 340° до 20° по часовой стрелке.
5. **true**: флаг, указывающий, следует ли рисовать сектор по часовой стрелке.
Вызов fillPath() применяет ранее заданный стиль заливки (fillStyle) и отрисовывает фигуру на экране.
Добавление интерактивности: setInteractive
Чтобы объект Graphics реагировал на события мыши, ему нужно назначить зону взаимодействия с помощью setInteractive(). В примере используется геометрическая форма Phaser.Geom.Circle и функция проверки Phaser.Geom.Circle.Contains.
graphics.setInteractive(new Phaser.Geom.Circle(400, 300, 200), Phaser.Geom.Circle.Contains);
Этот код создает невидимую область взаимодействия в форме круга с центром в (400, 300) и радиусом 200 пикселей. События мыши (pointerover, pointerout) будут срабатывать, только когда курсор находится внутри этого круга, а не строго внутри нарисованного желтого сектора. Это упрощает логику взаимодействия для пользователя.
Обработка событий и динамическое перерисовывание
Объект Graphics может прослушивать стандартные события ввода. В примере обрабатываются pointerover (курсор над объектом) и pointerout (курсор покинул объект).
Ключевой момент: перед изменением внешнего вида графику нужно очистить с помощью метода clear(). Иначе новые фигуры будут рисоваться поверх старых.
graphics.on('pointerover', () => {
graphics.clear();
graphics.fillStyle(0xff0000, 1);
graphics.slice(400, 300, 200, Phaser.Math.DegToRad(340), Phaser.Math.DegToRad(20), true);
graphics.fillPath();
});
При наведении курсора (pointerover) фигура очищается, стиль заливки меняется на красный, и тот же самый сектор перерисовывается. При уходе курсора (pointerout) происходит обратный процесс: очистка и отрисовка сектора с исходным желтым цветом.
Что попробовать дальше
Объект Graphics предоставляет гибкий API для создания и управления векторной графикой прямо в игровом цикле. Вы научились рисовать фигуры, назначать им зоны взаимодействия и динамически менять их в ответ на действия игрока. Для экспериментов попробуйте изменить форму: используйте fillRect() или fillCircle(). Добавьте анимацию плавного изменения цвета или радиуса внутри обработчиков событий. Или создайте сложный составной UI-элемент, собранный из нескольких графических объектов.
