О чем этот пример
Работа с повторяющимися текстурами — обычная задача в геймдеве. В Phaser для этого есть специальный объект `TileSprite`, который эффективно рендерит крупные фоны или повторяющиеся элементы. Но что, если нужно зеркально отразить такую текстуру? В этой статье разберем, как работают флаги `flipX` и `flipY` для тайл-спрайтов, и почему их использование не требует создания дополнительных изображений в памяти. Это простой и оптимизированный способ добавить вариативности в ваши игры.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
image1;
image0;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('image0', 'assets/pics/ra-einstein.png');
this.load.image('image1', 'assets/sprites/mushroom2.png');
}
create ()
{
this.image0 = this.add.tileSprite(400, 300, 500.5, 500, 'image0');
this.image1 = this.add.tileSprite(400, 300, 150, 150, 'image1');
// image0.flipX = true;
// image1.flipY = true;
}
}
const config = {
type: Phaser.CANVAS,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что такое TileSprite и зачем он нужен
В отличие от обычного спрайта (Sprite), который отображает одно изображение целиком, TileSprite (тайл-спрайт) предназначен для работы с повторяющимися текстурами. Вы задаете ему размер (width, height), и текстура будет заполнять эту область, при необходимости повторяясь (тайлинг). Это идеально для создания бесконечных фонов, крупных текстурных поверхностей или повторяющихся узоров без загрузки гигантских изображений.
Пример создания двух тайл-спрайтов разного размера:
this.image0 = this.add.tileSprite(400, 300, 500.5, 500, 'image0');
this.image1 = this.add.tileSprite(400, 300, 150, 150, 'image1');
Первый спрайт (image0) использует текстуру Эйнштейна размером 500.5x500 пикселей. Обратите внимание, что ширина может быть дробной. Второй спрайт (image1) — это гриб размером 150x150 пикселей. Оба отцентрированы в точке (400, 300).
Свойства flipX и flipY: зеркальное отражение на лету
Ключевая особенность тайл-спрайтов, как и многих других игровых объектов в Phaser, — наличие булевых свойств flipX и flipY. Установив их в true, вы мгновенно зеркально отражаете текстуру по горизонтали или вертикали соответственно.
Это происходит на уровне рендеринга, без создания копии исходного изображения в памяти. Phaser просто меняет порядок отрисовки текстуры внутри отведенной области. Раскомментируйте строки в исходном примере, чтобы увидеть эффект:
image0.flipX = true; // Отразить фон с Эйнштейном по горизонтали
image1.flipY = true; // Отразить спрайт гриба по вертикали
После этого image0 (текстура Эйнштейна) будет отражена зеркально слева направо, а image1 (гриб) — сверху вниз. Изменения вступают в силу немедленно в том же кадре.
Как это работает под капотом и почему это эффективно
Когда вы устанавливаете flipX или flipY, движок не манипулирует пикселями исходного изображения (текстуры). Вместо этого он меняет параметры UV-координат или матрицу трансформации, которые используются при отрисовке этого конкретного игрового объекта на холсте или WebGL-контексте.
UV-координаты — это способ «натянуть» текстуру на геометрию объекта. По умолчанию они идут от (0,0) в левом верхнем углу текстуры до (1,1) в правом нижнем. При flipX движок меняет порядок по горизонтали, например, от (1,0) до (0,1). Это крайне дешевая операция, стоимость которой сравнима с обычным перемещением или поворотом спрайта.
Такой подход дает огромное преимущество: вы можете создать одну текстуру, а затем использовать ее в нескольких тайл-спрайтах с разными вариантами отражения, не расходуя лишнюю оперативную память на хранение перевернутых копий.
Практическое применение в играх
Зеркальное отражение — это не просто визуальный эффект, а мощный инструмент для геймдизайна и оптимизации.
* **Создание симметричных уровней:** Представьте платформер с пещерой. Вы можете создать одну текстуру стены, а затем, используя flipX, сделать левую и правую часть пещеры симметричными, избегая ощущения «клонирования».
* **Анимация персонажей:** Если ваш персонаж может смотреть влево и вправо, часто достаточно двух наборов анимаций (например, вид спереди и сзади). Для движения влево можно использовать спрайт для движения вправо, но с установленным flipX = true. Это сокращает объем работы художнику и размер атласа анимаций.
* **Вариативность фонов:** Одна текстура травы, отраженная несколько раз, может создать более естественный и менее повторяющийся ландшафт.
Пример для симметричного фона:
// Создаем основную текстуру фона
let leftPart = this.add.tileSprite(200, 300, 400, 600, 'caveWall');
// Создаем правую часть, зеркально отразив левую
let rightPart = this.add.tileSprite(600, 300, 400, 600, 'caveWall');
rightPart.flipX = true;
Что попробовать дальше
Свойства flipX и flipY у TileSprite — это пример элегантной и производительной философии Phaser. Они позволяют добиться значительного визуального разнообразия, используя минимальные ресурсы. Для экспериментов попробуйте менять эти свойства динамически в цикле обновления (update) в зависимости от действий игрока (например, отражение спрайта при изменении направления движения) или создайте сложный узор, комбинируя несколько тайл-спрайтов с разными настройками отражения. Помните, что эти свойства работают и для обычных Sprite объектов, открывая еще больше возможностей для оптимизации арта.
