О чем этот пример
Создание плавных и сложных анимаций — ключ к визуальной привлекательности игры. Часто требуется изменить внешний вид объекта прямо в середине движения, например, чтобы карта перевернулась и показала другую сторону. Phaser 3 позволяет управлять не только стандартными свойствами вроде `scale` или `alpha`, но и менять текстуру объекта с помощью твинов, создавая бесшовные переходы. В этой статье мы разберем, как используя один твин-цепочку (`tweens.add`) анимировать сжатие по горизонтали и последующую смену текстуры с точной синхронизацией по времени, что идеально подходит для эффектов трансформации.
Версия 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('back', 'assets/tweens/cardback.png');
this.load.image('front', 'assets/tweens/cardfront.png');
}
create ()
{
const card1 = this.add.image(180, 300, 'back');
const card2 = this.add.image(400, 300, 'back');
const card3 = this.add.image(620, 300, 'back');
// Scale the card horizontally to zero (which takes 1 second)
// Then change the texture to the front of the card
// The 'yoyo' in the scaleX will reverse it back again
this.tweens.add({
targets: card1,
props: {
scaleX: { value: 0, duration: 1000, yoyo: true },
texture: { value: 'front', duration: 0, delay: 1000 }
},
ease: 'Linear'
});
this.tweens.add({
targets: card2,
props: {
scaleX: { value: 0, duration: 1000, yoyo: true },
texture: { value: 'front', duration: 0, delay: 1500 }
},
ease: 'Linear',
delay: 500
});
this.tweens.add({
targets: card3,
props: {
scaleX: { value: 0, duration: 1000, yoyo: true },
texture: { value: 'front', duration: 0, delay: 2000 }
},
ease: 'Linear',
delay: 1000
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и загрузка ресурсов
В методе preload мы загружаем две текстуры: рубашку карты (cardback.png) и её лицевую сторону (cardfront.png). Базовая ссылка указывает на публичный репозиторий с примерами Phaser, но в реальном проекте вы будете использовать локальные пути.
В create создаются три спрайта карт с начальной текстурой рубашки. Они позиционируются по горизонтали для наглядности.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('back', 'assets/tweens/cardback.png');
this.load.image('front', 'assets/tweens/cardfront.png');
}
create ()
{
const card1 = this.add.image(180, 300, 'back');
const card2 = this.add.image(400, 300, 'back');
const card3 = this.add.image(620, 300, 'back');
// ... твины
}
Анатомия твина: управление несколькими свойствами
Ключевой инструмент — метод this.tweens.add. Он принимает объект конфигурации. Внутри свойства props мы можем определить несколько анимируемых характеристик цели (targets). Каждое свойство (например, scaleX или texture) настраивается своим объектом параметров. Это позволяет создавать сложные цепочки действий в рамках одной анимации.
this.tweens.add({
targets: card1,
props: {
scaleX: { value: 0, duration: 1000, yoyo: true },
texture: { value: 'front', duration: 0, delay: 1000 }
},
ease: 'Linear'
});
Здесь targets — это наш спрайт card1. Для свойства scaleX задано значение `0(полное сжатие по ширине) с длительностьюduration: 1000мс. Параметрyoyo: trueуказывает, что после достижения нуля анимация масштаба автоматически воспроизведётся в обратном порядке, вернув карту к исходной ширине. Свойствоtextureменяет ключ текстуры спрайта на'front'. Важный момент:duration: 0означает мгновенную смену, аdelay: 1000откладывает это действие ровно на время, за котороеscaleX` доходит до нуля.
Синхронизация и последовательность анимаций
В примере три карты переворачиваются с задержкой, создавая волнообразный эффект. Это достигается двумя механизмами:
1. **Задержка смены текстуры внутри твина (delay в texture).** У первой карты задержка 1000 мс, у второй — 1500 мс, у третьей — 2000 мс. Это определяет, *когда* внутри своей анимационной цепочки карта поменяет картинку.
2. **Общая задержка запуска самого твина (delay на верхнем уровне).** Вторая карта начинает свою анимацию на 500 мс позже первой, а третья — на 1000 мс позже. Это определяет, *когда* весь процесс (сжатие и смена) начнётся для каждой карты.
// Для card2: общая задержка старта + задержка смены текстуры
this.tweens.add({
targets: card2,
props: {
scaleX: { value: 0, duration: 1000, yoyo: true },
texture: { value: 'front', duration: 0, delay: 1500 }
},
ease: 'Linear',
delay: 500 // Общая задержка старта твина
});
Таким образом, вторая карта начнёт сжиматься через 500 мс после первой, а сменит текстуру через 1500 мс после *начала своей собственной анимации*.
Конфигурация игры и запуск сцены
Стандартная конфигурация игры Phaser 3. Важно, что в свойстве scene передаётся класс нашей сцены Example. После создания экземпляра Phaser.Game автоматически вызываются методы жизненного цикла сцены: preload, create и далее update.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
Использование props в твинах Phaser 3 открывает мощный способ создания синхронизированных анимаций, объединяющих трансформацию и смену визуального представления объекта. Этот подход гораздо чище и управляемее, чем ручной расчёт таймеров. Для экспериментов попробуйте: заменить scaleX на scaleY для вертикального переворота; использовать другую ease-функцию (например, Power2) для более динамичного сжатия; или добавить третье свойство, например, angle, чтобы карта одновременно поворачивалась.
