О чем этот пример
Анимации на основе tween (или 'твинов') — это мощный инструмент для создания плавного движения в играх. Но что, если нужно не просто запустить анимацию с начала, а перескочить в её середину или перемотать? Метод `tween.seek()` даёт вам точный контроль над временной шкалой твина, позволяя мгновенно перемещать объект в любую точку анимационного пути. Это полезно для реализации функций перемотки кат-сцен, создания интерактивных элементов, реагирующих на клик, или для отладки сложных последовательностей движения.
Версия 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('bg', 'assets/skies/space2.png');
this.load.image('car', 'assets/sprites/car-yellow.png');
}
create ()
{
this.add.image(400, 300, 'bg');
const car = this.add.image(0, 300, 'car')
const tween = this.add.tween({
targets: car,
x: 800,
duration: 4000,
yoyo: true,
ease: 'Linear',
repeat: -1
});
// tween.seek(0.5);
this.input.on('pointerdown', (pointer) => {
// if (pointer.x > 400)
// {
// tween.forward(500);
// }
// else
// {
// tween.rewind(500);
// }
tween.seek(1000);
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Суть метода Tween.seek()
Метод tween.seek() позволяет мгновенно переместить воспроизведение твина в указанную временную позицию. Вы задаёте значение в миллисекундах от начала анимации, и все свойства целевых объектов немедленно обновляются, как если бы твин проигрывался до этого момента.
Это отличается от паузы или остановки. seek() не влияет на состояние воспроизведения (playback state) твина — если твин был активен, он продолжит проигрываться с новой позиции. Это мощный инструмент для нелинейного управления анимацией.
Разбираем пример кода
В примере создаётся бесконечно повторяющийся твин для автомобиля, который движется от x:0 до x:800 и обратно (благодаря флагу yoyo).
const tween = this.add.tween({
targets: car,
x: 800,
duration: 4000,
yoyo: true,
ease: 'Linear',
repeat: -1
});
Изначально строка tween.seek(0.5); закомментирована. Если её раскомментировать, твин начнёт воспроизведение не с начальной позиции машины (x=0), а с позиции, соответствующей 0.5 миллисекундам от его продолжительности. Так как длительность 4000мс, это практически начало, и видимого эффекта не будет. Для работы seek() с долями необходимо использовать значение от 0 до 1, что в текущем API Phaser 3 не поддерживается — метод ожидает время в миллисекундах.
Основная логика привязана к событию клика (pointerdown). При любом клике на сцену вызывается tween.seek(1000).
this.input.on('pointerdown', (pointer) => {
tween.seek(1000);
});
Это означает: независимо от того, где сейчас находится машина в своём цикле анимации, она мгновенно «перепрыгнет» в состояние, в котором была бы на 1000-й миллисекунде (1 секунде) проигрывания твина с самого начала. Так как полный путь в одну сторону длится 4000мс, через 1000мс машина окажется на четверти пути, то есть примерно на x:200.
Практическое применение и вариации
Метод seek() раскрывает свой потенциал в сочетании с другими методами управления твинами. В закомментированном коде примера показана альтернативная логика, основанная на позиции клика и методах forward() и rewind(). Это наводит на мысль о более сложных сценариях.
Например, можно создать интерактивный ползунок прогресса для анимации:
// Предположим, у нас есть слайдер, который возвращает значение от 0 до 1
slider.on('change', (value) => {
// Переводим долю от общей длины анимации в миллисекунды
const seekTime = value * tween.totalDuration;
tween.seek(seekTime);
});
Или использовать seek() для синхронизации нескольких твинов, запуская их с разных временных точек для создания сложных сценарных последовательностей.
Важные нюансы и ограничения
1. **Аргумент в миллисекундах:** seek(time) принимает время в миллисекундах, а не нормализованное значение от 0 до 1. Используйте tween.totalDuration для расчётов.
2. **Влияние на repeat и yoyo:** Метод учитывает общую прогрессию твина, включая повторы (repeat) и возвраты (yoyo). seek(5000) в твине длительностью 4000мс с repeat: -1 переведёт его во время 1000мс второго повторения.
3. **Мгновенное обновление:** Переход происходит без интерполяции. Если нужна плавная перемотка, используйте комбинацию tween.stop(), tween.seek() и tween.play() или методы forward()/rewind().
4. **Состояние твина:** seek() не меняет состояния (isPlaying, isPaused). Если твин был на паузе, он останется на паузе в новой позиции.
Что попробовать дальше
Метод Tween.seek() — это ваш шанс напрямую взаимодействовать с временной осью анимации в Phaser. Он открывает двери для создания нелинейного, реактивного и отлаживаемого геймплея. Для экспериментов попробуйте: создать систему «призрака» в гонке, записывая траекторию и используя seek() для её воспроизведения; реализовать интерактивную временную шкалу для кат-сцены; или связать прогресс твина со звуковой дорожкой для идеальной аудиовизуальной синхронизации.
