О чем этот пример
Создание интерфейса, который корректно отображается на экранах любого размера — ключевая задача для разработчика игр. Классическое масштабирование спрайтов часто приводит к растягиванию углов и потере деталей, из-за чего UI выглядит дешево и неаккуратно. В этой статье мы разберем, как использовать технику Nine Slice в Phaser для создания интерфейсных элементов, которые масштабируются правильно, сохраняя четкие углы и пропорционально растягивая только центральные части.
Версия 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.atlas('ui', 'assets/ui/nine-slice.png', 'assets/ui/nine-slice.json');
}
create ()
{
const panel = this.add.nineslice(0, 0, 'ui', 'PopupBackground400', 400, 275, 160, 160, 100, 100).setOrigin(0, 0);
const image = this.add.image(400, 0, 'ui', 'PopupBackground400').setOrigin(0, 0);
this.tweens.add({
targets: panel,
height: 600,
duration: 6000,
ease: 'sine.inout',
yoyo: true,
repeat: -1,
});
this.tweens.add({
targets: image,
displayHeight: 600,
duration: 6000,
ease: 'sine.inout',
yoyo: true,
repeat: -1,
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#005826',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что такое Nine Slice?
Nine Slice (или 9-slice scaling) — это техника масштабирования двумерных изображений, при которой спрайт мысленно делится на девять частей: четыре угла, четыре края и центральная область. При изменении размеров объекта углы остаются неизменными, края растягиваются только в одном направлении (вертикально или горизонтально), а центральная часть — в обоих.
Это идеально подходит для панелей, кнопок, окон диалогов и других UI-элементов, где важно сохранить четкость рамок и скругленных углов при любых размерах. В Phaser для работы с этой техникой используется специальный Game Object — NineSlice.
Создание Nine Slice объекта в Phaser
В приведенном примере для создания панели используется метод this.add.nineslice(). Его ключевое отличие от обычного this.add.image() — наличие параметров, определяющих размеры срезов.
Давайте посмотрим на вызов конструктора:
const panel = this.add.nineslice(0, 0, 'ui', 'PopupBackground400', 400, 275, 160, 160, 100, 100).setOrigin(0, 0);
Разберем аргументы по порядку:
1. **0, 0** — координаты X и Y для размещения объекта.
2. **'ui'** — ключ атласа текстур, загруженного в preload.
3. **'PopupBackground400'** — ключ конкретного кадра (фрейма) внутри атласа.
4. **400, 275** — начальная ширина и высота создаваемого объекта.
5. **160, 160** — ширина и высота левого верхнего угла. Эти значения определяют размер неизменяемой угловой зоны.
6. **100, 100** — ширина и высота правого нижнего угла. Вместе с предыдущими параметрами они задают размеры всех четырех углов и, косвенно, краев.
Phaser автоматически вычисляет, какие части исходного изображения являются углами, краями и центром, и применяет к ним правильные правила масштабирования.
Проблема обычного масштабирования (Scaling)
Для сравнения рядом с Nine Slice панелью создается обычное изображение:
const image = this.add.image(400, 0, 'ui', 'PopupBackground400').setOrigin(0, 0);
Это стандартный спрайт. Когда мы меняем его свойство displayHeight (или displayWidth), масштабируется всё изображение целиком, включая углы и рамки. Это приводит к их искажению — они становятся размытыми, растянутыми или сплющенными, в зависимости от пропорций. Такой подход быстро выдает низкокачественный интерфейс.
Наглядная демонстрация с помощью Tween
В примере используются два твина для анимации, которые наглядно демонстрируют разницу между подходами. Оба твина изменяют высоту объектов от исходной до 600 пикселей и обратно.
Твин для Nine Slice панели анимирует стандартное свойство height:
this.tweens.add({
targets: panel,
height: 600,
duration: 6000,
ease: 'sine.inout',
yoyo: true,
repeat: -1,
});
Твин для обычного изображения анимирует свойство displayHeight, которое отвечает за визуальное масштабирование:
this.tweens.add({
targets: image,
displayHeight: 600,
duration: 6000,
ease: 'sine.inout',
yoyo: true,
repeat: -1,
});
Запустив этот код, вы сразу увидите разницу: панель Nine Slice будет плавно увеличиваться в высоту, при этом ее верхняя и нижняя рамки (края) растянутся, а скругленные углы сохранят свою идеальную форму. Обычное изображение будет выглядеть так, как будто его тянут за верх и низ — углы истончатся и деформируются.
Практические советы по использованию
1. **Подготовка ассетов:** Для Nine Slice нужен спрайт, углы и рамки которого имеют достаточный "запас" пикселей. Центральная часть может быть однотонной или с простым повторяющимся узором.
2. **Определение размеров срезов:** Параметры leftWidth, rightWidth, topHeight, bottomHeight (в примере задаются через размеры углов) — это самые важные значения. Они должны точно соответствовать пиксельным размерам угловых областей на вашем исходном изображении. Неправильные значения приведут к визуальным артефактам.
3. **Использование с контейнерами:** NineSlice объекты можно помещать внутрь Container вместе с текстом, иконками и другими элементами UI для построения сложных интерфейсов.
4. **Изменение размеров:** Меняйте свойства width и height объекта, а не scaleX/scaleY. Изменение масштаба (scale) также будет работать, но прямое управление размерами чаще бывает интуитивно понятнее для UI.
Что попробовать дальше
Nine Slice — это обязательный инструмент в арсенале разработчика, который заботится о качестве пользовательского интерфейса. Он решает конкретную проблему деформации элементов при масштабировании, обеспечивая профессиональный вид вашей игры.
**Идеи для экспериментов:**
1. Попробуйте создать кнопку с помощью NineSlice и анимировать ее свойство width при наведении курсора, чтобы получить эффект "резиновой" кнопки с неизменными углами.
2. Скомбинируйте несколько NineSlice объектов разного цвета и размера, чтобы создать сложное модальное окно с заголовком, телом и нижней панелью действий.
3. Испытайте технику на спрайтах с более сложными рамками (например, с деревянной или каменной текстурой) и подберите оптимальные размеры срезов.
