О чем этот пример
Часто при создании анимаций нужно сдвинуть объект не в конкретную точку на экране, а относительно его текущего положения. Например, чтобы вражеский корабль пролетел вверх на 200 пикселей или чтобы бонус подпрыгнул. В таких случаях на помощь приходят относительные значения в твинах Phaser. Эта статья покажет, как легко и эффективно анимировать объекты, используя синтаксис '+=value' и '-=value' для создания динамичных и переиспользуемых движений.
Версия 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('block', 'assets/sprites/block.png');
}
create ()
{
var image = this.add.image(100, 100, 'block');
var tween = this.tweens.add({
targets: image,
props: {
x: { value: '+=500', duration: 3000, ease: 'Power2' },
y: { value: '+=300', duration: 1500, ease: 'Bounce.easeOut' }
},
delay: 1000
});
console.log(tween);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что такое относительное значение в твине?
В Phaser твин — это инструмент для плавного изменения свойств объекта (позиции, прозрачности, масштаба) со временем. Обычно вы указываете абсолютное конечное значение, например, x: 600. Но иногда нужно сказать "сдвинься на 500 пикселей вправо от того места, где ты сейчас стоишь". Для этого используется специальный строковый синтаксис.
Относительное значение записывается как строка, начинающаяся с операторов += (прибавить) или -= (вычесть), за которыми следует число. Движок сам вычислит итоговую цель, прибавив или вычтя это число из текущего значения свойства в момент старта твина.
Разбор примера: анимация блока
Рассмотрим исходный код примера. В нем создается простой спрайт и к нему применяется твин с двумя относительными изменениями.
var image = this.add.image(100, 100, 'block');
Сначала в точке (100, 100) создается изображение блока.
var tween = this.tweens.add({
targets: image,
props: {
x: { value: '+=500', duration: 3000, ease: 'Power2' },
y: { value: '+=300', duration: 1500, ease: 'Bounce.easeOut' }
},
delay: 1000
});
Здесь создается твин. Ключевые моменты:
1. `targets: image` — объект, который будет анимирован.
2. Внутри `props` задаются свойства для анимации.
* `x: { value: '+=500', ... }` — свойство `x` (горизонтальная позиция) увеличится на 500 пикселей. Так как блок стартовал на `x=100`, он остановится на `x=600`.
* `y: { value: '+=300', ... }` — свойство `y` (вертикальная позиция) увеличится на 300 пикселей. От начальной точки `y=100` блок переместится до `y=400`.
3. `duration` задает длительность анимации для каждого свойства независимо. Обратите внимание, что движение по оси X длится 3 секунды, а по оси Y — 1.5 секунды. Это создает диагональное движение с разной скоростью.
4. `ease` определяет функцию плавности. `'Power2'` — равномерное ускорение и замедление для оси X. `'Bounce.easeOut'` — создает эффект отскока в конце движения по оси Y.
5. `delay: 1000` — твин начнется с задержкой в 1 секунду после вызова метода.
Практическая польза и сценарии использования
Использование относительных значений делает код анимаций более гибким и независимым от конкретных координат.
* **Переиспользуемые анимации:** Вы можете создать функцию, которая заставляет любой переданный объект подпрыгнуть (y: '-=80'), не зная его изначальной позиции.
* **Цепочки движений:** Легко создавать последовательные твины. Например, объект двигается вправо, а затем, после завершения первого твина, запускается второй с '+=100', чтобы продолжить путь.
* **Динамическая реакция:** В игровой логике можно рассчитать силу толчка ('+=speedX') и применить ее к позиции игрока при столкновении.
Важно помнить, что вычисление конечной цели происходит один раз — в момент старта твина. Если вы измените свойство объекта (например, image.x) во время выполнения анимации, конечная точка не пересчитается.
Независимые свойства и объект `props`
В примере используется структура props, внутри которой каждое свойство (`x,y`) настраивается своим объектом конфигурации. Это мощная особенность API твинов Phaser.
props: {
x: { value: '+=500', duration: 3000, ease: 'Power2' },
y: { value: '+=300', duration: 1500, ease: 'Bounce.easeOut' }
}
Благодаря этому вы можете задать:
* Разную длительность (duration) для каждой оси.
* Разные функции плавности (ease).
* Разные задержки (delay) для начала анимации каждого свойства (в примере не показано, но возможно).
* Разные типы значений: одно свойство может меняться на абсолютное число, другое — на относительное, третье — по заранее заданному пути.
Это дает тонкий контроль над сложными составными анимациями, как в нашем случае, где движение вниз (`y) завершается отскоком и заканчивается раньше, чем горизонтальное движение (x`).
Что попробовать дальше
Относительные значения в твинах — это простой, но мощный инструмент для создания гибких и переиспользуемых анимаций в Phaser. Они идеально подходят для описания движения "относительно текущего состояния", что часто требуется в геймдеве.
**Идеи для экспериментов:**
1. Замените '+=' на '-=' и посмотрите, как изменится направление движения.
2. Создайте цепочку твинов с помощью события onComplete, где каждый последующий твин использует относительное значение для продолжения пути объекта по сложной траектории (например, зигзагу).
3. Скомбинируйте относительное изменение позиции (`x,y) с абсолютным изменением других свойств, например, прозрачности (alpha: 0) или угла поворота (angle: 180`).
