О чем этот пример
Этот пример демонстрирует мощь Phaser для создания визуальных эффектов, характерных для демосцены. Мы разберем, как с помощью одной текстуры, группы спрайтов, тонирования и цепочек анимаций создать гипнотический движущийся 'ковер'. Этот подход полезен для создания фоновых эффектов, переходов или просто для изучения работы с группами (`Group`) и менеджером анимаций (`Tweens`).
Версия 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('raster', 'assets/demoscene/raster-w-800x16.png');
this.load.image('raster', 'assets/demoscene/raster-bw-800x16.png');
}
create ()
{
const group = this.add.group();
group.createMultiple({ key: 'raster', repeat: 64 });
const hsv = Phaser.Display.Color.HSVColorWheel();
let i = 0;
const _this = this;
group.children.forEach(child =>
{
child.x = 500;
child.y = 100;
child.depth = 64 - i;
child.scaleX = 0.6;
// child.setBlendMode(Phaser.BlendModes.ADD);
child.setTint(hsv[i * 4].color);
i++;
_this.tweens.add({
targets: child,
props: {
x: { value: 300, duration: 700 },
y: { value: 500, duration: 2500 },
scaleX: { value: Math.min(0.1, child.depth / 64), duration: 4000, hold: 2000, delay: 2000 }
},
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut',
delay: 38 * i
});
});
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Подготовка ресурсов и создание группы
В методе preload загружается одна текстурная полоса raster. Ключевой объект здесь — группа (Group). Группа позволяет управлять множеством игровых объектов как единым целым, что идеально для повторяющихся элементов.
const group = this.add.group();
group.createMultiple({ key: 'raster', repeat: 64 });
Вызов createMultiple создает 65 спрайтов (1 оригинальный + 64 повторения), используя загруженное изображение 'raster' в качестве текстуры. Все они автоматически добавляются в группу group.
Настройка спрайтов: позиция, глубина и цвет
Далее в цикле forEach мы настраиваем каждый созданный спрайт (child). Изначально все спрайты позиционируются в одной точке (x: 500, y: 100).
child.depth = 64 - i;
child.scaleX = 0.6;
child.setTint(hsv[i * 4].color);
- depth определяет порядок отрисовки. Спрайты с большим значением будут рисоваться поверх других. Здесь он убывает, создавая основу для перспективы.
- scaleX сжимает спрайт по горизонтали, превращая квадратную текстуру в вертикальную полосу.
- setTint применяет цвет из заранее сгенерированной палитры hsv. Phaser.Display.Color.HSVColorWheel() создает массив из 360 цветов, что позволяет легко получить плавный градиент по индексу `i`.
Создание цепочек анимаций с помощью Tweens
Сердце эффекта — система твинов. Для каждого спрайта создается цепочка анимаций, управляемая одним твин-менеджером.
_this.tweens.add({
targets: child,
props: {
x: { value: 300, duration: 700 },
y: { value: 500, duration: 2500 },
scaleX: { value: Math.min(0.1, child.depth / 64), duration: 4000, hold: 2000, delay: 2000 }
},
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut',
delay: 38 * i
});
- targets: объект для анимации.
- props: свойства для изменения. Каждое свойство (`x,y,scaleX) имеет свои параметры: конечноеvalue, длительностьduration, задержкуdelayи время удержанияhold`.
- yoyo: true заставляет анимацию проигрываться в обратном порядке после завершения.
- repeat: -1 устанавливает бесконечное повторение.
- ease: функция плавности 'Sine.easeInOut' для мягкого ускорения и замедления.
- delay: задержка старта анимации для каждого спрайта, увеличивающаяся с индексом `i`. Это создает волнообразный, последовательный эффект движения.
Сборка сцены и конфигурация игры
Класс Example расширяет Phaser.Scene. Вся логика содержится в стандартных методах сцены preload и create.
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Объект config передается в конструктор Phaser.Game, запуская игровой цикл. Параметр scene указывает на наш класс сцены, который будет инстанциирован автоматически.
Что попробовать дальше
Пример показывает, как из минимальных элементов — одной текстуры и грамотного кода — рождается сложный визуальный паттерн. Для экспериментов попробуйте: изменить палитру (использовать RGB вместо HSV), добавить вращение через angle, применить другой бленд-мод (раскомментировать setBlendMode), или варьировать формулу delay для создания иных волновых эффектов.
