О чем этот пример
Создание плавной и живой анимации — ключ к увлекательному геймплею. В этой статье разберем, как с помощью графического объекта (`Graphics`) и системы твинов (`Tweens`) создать простую, но выразительную анимацию персонажа прямо в коде, без использования внешних спрайтов. Этот подход полезен для прототипирования, создания эффектов частиц или нестандартных UI-элементов.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
const graphics = this.add.graphics();
this.tweens.addCounter({
from: 0,
to: 30,
duration: 200,
yoyo: true,
repeat: -1,
onUpdate: function (tween)
{
const t = tween.getValue();
graphics.clear();
graphics.fillStyle(0xffff00, 1);
graphics.slice(260, 300, 200, Phaser.Math.DegToRad(330 + t), Phaser.Math.DegToRad(30 - t), true);
graphics.fillPath();
graphics.fillStyle(0x000000, 1);
graphics.fillEllipse(260, 180, 30, 90);
graphics.fillStyle(0xffffff, 1);
graphics.fillCircle(580, 300, 30);
graphics.fillCircle(740, 300, 30);
}
});
}
}
const config = {
width: 800,
height: 600,
backgroundColor: '#010166',
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Создание графического контекста и твина
В методе create() сцены мы создаем основной инструмент для рисования — объект graphics. Затем сразу инициируем анимацию с помощью this.tweens.addCounter. Этот твин управляет числовым значением, которое будет меняться от 0 до 30 и обратно.
const graphics = this.add.graphics();
this.tweens.addCounter({
from: 0,
to: 30,
duration: 200,
yoyo: true,
repeat: -1,
onUpdate: function (tween)
{
// Код для перерисовки
}
});
Ключевые параметры твина:
* duration: 200 — один цикл (от 0 до 30) длится 200 миллисекунд.
* yoyo: true — значение после достижения максимума вернется к минимуму.
* repeat: -1 — анимация будет повторяться бесконечно.
* onUpdate — функция, вызываемая на каждом кадре анимации. Именно здесь происходит вся отрисовка.
Отрисовка "рта" Пакмана
Внутри функции onUpdate мы получаем текущее значение твина (`t`) и используем его для динамического расчета углов.
Первым делом холст очищается вызовом graphics.clear(). Это важно, иначе каждый кадр будет рисоваться поверх предыдущего.
graphics.clear();
graphics.fillStyle(0xffff00, 1);
graphics.slice(260, 300, 200, Phaser.Math.DegToRad(330 + t), Phaser.Math.DegToRad(30 - t), true);
graphics.fillPath();
Метод graphics.slice рисует сектор (как кусок пирога). Его параметры:
1. 260, 300 — координаты X и Y центра сектора.
2. 200 — радиус.
3. Phaser.Math.DegToRad(330 + t) — начальный угол. Он увеличивается от 330 градусов, заставляя правую сторону рта открываться.
4. Phaser.Math.DegToRad(30 - t) — конечный угол. Он уменьшается от 30 градусов, заставляя левую сторону рта открываться. Функция Phaser.Math.DegToRad конвертирует градусы в радианы, как того требует API.
5. true — рисовать сектор по часовой стрелке.
В результате углы симметрично расходятся и сходятся, создавая иллюзию жевания.
Добавление статичных элементов
После отрисовки анимированного рта мы добавляем статичные детали, которые не меняются от кадра к кадру. Это демонстрирует, что в одном графическом объекте можно комбинировать динамические и статические элементы.
graphics.fillStyle(0x000000, 1);
graphics.fillEllipse(260, 180, 30, 90);
// Призраки (точки-глаза)
graphics.fillStyle(0xffffff, 1);
graphics.fillCircle(580, 300, 30);
graphics.fillCircle(740, 300, 30);
Сначала черным цветом рисуется вытянутый эллипс (fillEllipse) над Пакманом — это его "глаз". Затем белым цветом рисуются два круга (fillCircle) в правой части экрана, изображающие глазки призраков. Их позиция и размер фиксированы.
Настройка игры (Config)
Конфигурационный объект config определяет базовые настройки игры. Размеры окна заданы как 800x600 пикселей.
const config = {
width: 800,
height: 600,
backgroundColor: '#010166',
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
Обратите внимание на свойство backgroundColor: '#010166'. Установка темно-синего фона (#010166) делает желтую фигуру Пакмана и белые круги визуально контрастными и яркими, что улучшает восприятие анимации.
Что попробовать дальше
Мы создали плавную анимацию, используя всего два инструмента Phaser: Graphics для рисования и Tweens для управления временем. Главный принцип — перерисовывать всю графику на каждом кадре анимации в функции onUpdate. Для экспериментов попробуйте изменить параметры твина (duration, from, to), чтобы ускорить или замедлить "жевание". Измените форму рта, используя graphics.arc вместо slice. Или добавьте второй твин, чтобы анимировать движение "глаза" Пакмана или мигание "призраков".
