О чем этот пример
Анимации — сердце любой живой игры. Статические перемещения объектов быстро наскучивают. В Phaser система Tween предлагает мощный инструмент: динамические свойства. Они позволяют вычислять начальные и конечные значения анимации на лету, прямо во время её выполнения. Это открывает двери для создания сложных, непредсказуемых и реактивных движений, которые отлично подходят для эффектов разрушения, хаотичного движения врагов или просто более "живых" интерфейсов. В этой статье мы разберем, как это работает, на конкретном примере с мячом, который меняет свою траекторию с каждым циклом.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
constructor()
{
super();
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('ball', 'assets/sprites/shinyball.png');
}
create ()
{
var image = this.add.image(100, 300, 'ball');
var destX = 700;
var tween = this.tweens.add({
targets: image,
duration: 500,
yoyo: true,
repeat: 8,
ease: 'Sine.easeInOut',
x: {
getEnd: function (target, key, value)
{
destX -= 30;
return destX;
},
getStart: function (target, key, value)
{
return value + 30;
}
}
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что такое динамические свойства?
Обычно, создавая твин, вы задаете конкретные числовые значения для свойств, например, x: 700. Объект плавно переместится из текущей позиции в точку x=700.
Динамические свойства заменяют эти статические числа функциями-геттерами. Phaser будет вызывать эти функции в ключевые моменты анимации, чтобы получить актуальное значение. Это позволяет анимации адаптироваться к изменяющимся условиям в игре.
В примере используется два таких геттера:
* getStart — вычисляет начальное значение свойства для каждого цикла твина.
* getEnd — вычисляет конечное значение свойства для каждого цикла твина.
Разбор примера: мяч с сужающейся амплитудой
Давайте построчно разберем ключевую часть кода — конфигурацию твина. Создается объект image (мяч) в точке (100, 300).
var tween = this.tweens.add({
targets: image,
duration: 500,
yoyo: true,
repeat: 8,
ease: 'Sine.easeInOut',
Здесь задаются базовые параметры: цель анимации (targets), длительность одного движения в миллисекундах (duration). Флаг yoyo: true означает, что после достижения конечной точки объект вернется назад. repeat: 8 установит количество полных повторов (туда-обратно). ease задает плавную синусоидальную функцию замедления в начале и конце.
Следующая часть — самое интересное: динамическое свойство `x`.
x: {
getEnd: function (target, key, value)
{
destX -= 30;
return destX;
},
getStart: function (target, key, value)
{
return value + 30;
}
}
Как работают getStart и getEnd
Функции getEnd и getStart вызываются движком Phaser. Они получают три аргумента: сам анимируемый объект (target), имя свойства (key, в нашем случае 'x') и текущее базовое значение (value).
1. **getEnd**: Эта функция определяет, *куда* полетит мяч. При первом вызове переменная destX равна 700. Функция уменьшает её на 30 (destX -= 30), становясь 670, и возвращает это значение. Таким образом, с каждым новым циклом (каждым движением "туда") конечная точка сдвигается на 30 пикселей влево.
2. **getStart**: Эта функция определяет, *откуда* начнется движение мяча в новом цикле. Она берет переданное текущее значение (value) — а это будет значение `xв момент старта нового цикла — и прибавляет к нему 30. Поскольку твин работает в режимеyoyo, мяч возвращается в точку старта предыдущего цикла.getStart` смещает эту точку, создавая эффект "дрейфа" всей траектории.
**Итоговое поведение:** Мяч бегает туда-сюда, но с каждым разом амплитуда его бега по оси X уменьшается, а весь путь смещается влево. Визуально это выглядит как затухающие колебания.
Практическое применение и вариации
Этот паттерн не ограничен свойством `x` или линейными изменениями. Вот несколько идей для использования:
* **Случайное движение:** Сделайте движение врага или частицы непредсказуемым.
y: {
getEnd: function() {
return Phaser.Math.Between(100, 500);
}
}
* **Реакция на игрока:** Дистанция или сила прыжка противника может зависеть от расстояния до героя.
* **Эффект "пьяной" камеры:** Динамически меняя scrollX и scrollY камеры через твины, можно создать эффект потрясения или дезориентации.
Важно помнить, что функции getStart и getEnd должны быть чистыми и быстрыми, чтобы не тормозить основной игровой цикл.
Что попробовать дальше
Динамические свойства в Phaser.Tweens — это мощный инструмент для выхода за рамки простых, предсказуемых анимаций. Они позволяют вплетать логику игры непосредственно в движение объектов, делая его отзывчивым и разнообразным. Для экспериментов попробуйте привязать вычисления в getEnd к состоянию другого игрового объекта, к скорости мыши или к данным из физического движка. Это оживит вашу игру совершенно новым способом.
