О чем этот пример
Визуальные манипуляции — ключевой элемент игровой динамики. В Phaser 3 объекты типа Rope, представляющие собой растяжимые поверхности из сегментов, поддерживают мгновенное отражение по горизонтали и вертикали. Этот пример демонстрирует, как с помощью всего двух методов API `toggleFlipX()` и `toggleFlipY()` реализовать интерактивное переворачивание анимированной верёвки, что полезно для создания зеркальных эффектов, изменяющихся фонов или инвертированной анимации персонажей без дублирования ресурсов.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
constructor ()
{
super();
this.rope;
this.count = 0;
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/rope/background-woof.png');
this.load.image('dog', 'assets/rope/doggo.png');
this.load.atlas('ui', 'assets/rope/ui-icons.png', 'assets/rope/ui-icons.json');
}
create ()
{
this.add.tileSprite(400, 300, 800, 600, 'bg');
this.add.text(10, 10, 'Click the arrows to flip', { font: '16px Courier', fill: '#000000' }).setShadow(1, 1, '#ffffff');
const rope = this.add.rope(400, 300, 'dog', null, 12);
const hFlip = this.add.image(80, 600-64, 'ui', 'forward-pink').setInteractive();
const vFlip = this.add.image(800-70, 600-80, 'ui', 'forward-pink').setAngle(-90).setInteractive();
hFlip.on('pointerdown', () => {
rope.toggleFlipX();
});
vFlip.on('pointerdown', () => {
rope.toggleFlipY();
});
this.rope = rope;
}
update ()
{
this.count += 0.1;
let points = this.rope.points;
for (let i = 0; i < points.length; i++)
{
points[i].y = Math.sin(i * 0.5 + this.count) * 10;
}
this.rope.setDirty();
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#000088',
parent: 'phaser-example',
scene: Example
};
let game = new Phaser.Game(config);
Инициализация сцены и загрузка ресурсов
Класс сцены наследуется от Phaser.Scene. В конструкторе инициализируются свойства для хранения ссылки на верёвку и счётчика для анимации.
В методе preload() загружаются необходимые ресурсы: фоновое изображение, текстура для верёвки (изображение собаки) и atlas для UI-кнопок. Обратите внимание на использование setBaseURL() для указания корневого пути.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/rope/background-woof.png');
this.load.image('dog', 'assets/rope/doggo.png');
this.load.atlas('ui', 'assets/rope/ui-icons.png', 'assets/rope/ui-icons.json');
}
Создание Rope и интерактивных элементов
В методе create() сначала добавляется фоновый TileSprite и информационный текст.
Затем создаётся основной объект — верёвка. Ключевой вызов this.add.rope() принимает координаты (400, 300), ключ текстуры 'dog', null вместо кадра анимации (так как используется статичное изображение) и число сегментов (12). Это определяет, на сколько частей будет разбита текстура для симуляции волны.
Далее создаются две кнопки из atlas 'ui'. Для вертикальной кнопки сразу применяется поворот .setAngle(-90). Метод setInteractive() делает их кликабельными.
const rope = this.add.rope(400, 300, 'dog', null, 12);
const hFlip = this.add.image(80, 600-64, 'ui', 'forward-pink').setInteractive();
const vFlip = this.add.image(800-70, 600-80, 'ui', 'forward-pink').setAngle(-90).setInteractive();
Обработка кликов и переворот
На каждую кнопку вешается обработчик события 'pointerdown'. При клике вызываются соответствующие методы объекта rope.
toggleFlipX() инвертирует отображение верёвки по горизонтали, а toggleFlipY() — по вертикали. Эти методы меняют внутренний флаг объекта, не требуя пересоздания или дополнительной настройки текстуры. Ссылка на объект верёвки сохраняется в свойстве сцены this.rope для доступа из метода update().
hFlip.on('pointerdown', () => {
rope.toggleFlipX();
});
vFlip.on('pointerdown', () => {
rope.toggleFlipY();
});
this.rope = rope;
Анимация волны и обновление
Метод update() выполняется каждый кадр и создаёт волнообразное движение верёвки. Счётчик this.count увеличивается, обеспечивая плавную анимацию.
Цикл проходит по всем точкам верёвки, доступным через массив this.rope.points. Для каждой точки вычисляется новое смещение по оси Y с помощью синуса, который зависит от индекса точки и значения счётчика. Это создаёт эффект бегущей волны.
После изменения точек необходимо вручную вызвать this.rope.setDirty(). Этот метод сообщает системе рендеринга, что геометрия верёвки изменилась и её нужно перерисовать. Без этого вызова визуальные изменения не применятся.
update ()
{
this.count += 0.1;
let points = this.rope.points;
for (let i = 0; i < points.length; i++)
{
points[i].y = Math.sin(i * 0.5 + this.count) * 10;
}
this.rope.setDirty();
}
Конфигурация и запуск игры
Объект config содержит стандартные настройки для Phaser Game: тип рендерера, размеры холста, цвет фона, ID родительского DOM-элемента и класс основной сцены.
Затем создаётся экземпляр игры new Phaser.Game(config), который запускает весь цикл.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#000088',
parent: 'phaser-example',
scene: Example
};
let game = new Phaser.Game(config);
Что попробовать дальше
Объекты Rope в Phaser 3 предлагают гибкий способ работы с деформируемыми текстурами. Использование toggleFlipX/Y() позволяет мгновенно менять их ориентацию, что можно применять для зеркальных отражений воды, перевёрнутых миров или двусторонних анимаций. Для экспериментов попробуйте
- Привязать переворот не к клику, а к положению персонажа
- Анимировать не только
points[i].y, но иpoints[i].xдля сложных деформаций - Комбинировать переворот с динамическим изменением текстуры верёвки
