О чем этот пример
9-слайсовые спрайты (nine slice) — это мощный инструмент для создания масштабируемых элементов интерфейса в играх. Вместо того чтобы растягивать текстуру целиком и получать размытые или деформированные края, вы задаёте области, которые могут безопасно растягиваться, сохраняя при этом чёткие углы и границы. Это незаменимо для кнопок, панелей, окон диалогов и других UI-элементов, размер которых может меняться динамически. В этой статье мы разберём, как работать с 9-слайсовыми спрайтами в 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/atlas/nine-slice.png', 'assets/atlas/nine-slice.json');
}
create ()
{
this.add.nineslice(400, 300, 'ui', 'blue-box', 600, 400);
this.add.nineslice(400, 300, 'ui', 'flectrum', 600);
this.add.nineslice(400, 300, 'ui', 'button-bg');
// this.add.nineslice(400, 300, 'ui', 'copy-that-floppy');
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#000000',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что такое 9-слайс и зачем он нужен
Представьте, что вам нужно нарисовать кнопку, ширина которой зависит от длины текста внутри. Если просто растянуть квадратную текстуру кнопки по горизонтали, её закруглённые углы исказятся, а границы станут слишком тонкими или толстыми. 9-слайс решает эту проблему.
Текстура мысленно делится на 9 частей (как сетка 3x3). Угловые части (1, 3, 7, 9) никогда не растягиваются. Боковые части (2 и 8) растягиваются только по горизонтали, а верхняя и нижняя (4 и 6) — только по вертикали. Центральная часть (5) растягивается по обоим направлениям. Такой подход сохраняет пропорции важных деталей (углов, границ) при любом размере объекта.
В Phaser для работы с 9-слайсом используется метод this.add.nineslice().
Подготовка атласа и загрузка ресурсов
Для использования 9-слайса текстуры должны быть подготовлены в атласе (texture packer) с корректно определёнными областями (frames). В примере используется атлас 'ui', состоящий из PNG-изображения и JSON-файла с описанием фреймов.
В методе preload() мы загружаем этот атлас. Ключевой момент — JSON-файл уже содержит данные о том, как именно нарезана текстура для каждого фрейма, включая информацию о 9-слайсе (если она была задана при создании атласа в редакторе, например, в Texture Packer или подобном).
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.atlas('ui', 'assets/atlas/nine-slice.png', 'assets/atlas/nine-slice.json');
}
Метод this.load.atlas() загружает изображение и JSON-манифест, связывая их под ключом 'ui'. Теперь мы можем обращаться к отдельным фреймам этого атласа по их именам, например, 'blue-box' или 'flectrum'.
Создание 9-слайсовых объектов разными способами
Основной метод для создания объекта — this.add.nineslice(x, y, texture, frame, width, height). Он принимает координаты, ключ текстуры (или атласа), имя фрейма из атласа, а также опциональные ширину и высоту итогового объекта.
В сцене create() показаны три варианта использования. Обратите внимание, как меняется поведение при указании разных параметров.
create ()
{
// Вариант 1: Указываем и ширину, и высоту.
this.add.nineslice(400, 300, 'ui', 'blue-box', 600, 400);
// Вариант 2: Указываем только ширину. Высота берётся из исходного фрейма.
this.add.nineslice(400, 300, 'ui', 'flectrum', 600);
// Вариант 3: Не указываем размеры. Объект создаётся в исходном размере фрейма.
this.add.nineslice(400, 300, 'ui', 'button-bg');
}
1. **Первый вызов:** Создаёт объект размером 600x400 пикселей на основе фрейма 'blue-box'. Все растягиваемые области будут масштабированы, чтобы заполнить эту площадь. 2. **Второй вызов:** Создаёт объект шириной 600 пикселей. Высота остаётся такой же, как у исходного фрейма 'flectrum'. Это полезно для создания горизонтальных полос или панелей. 3. **Третий вызов:** Создаёт объект в его "нативном" размере, как он определён в атласе. Это подходит для статических элементов, которые не планируется масштабировать.
Настройка сцены и запуск игры
Конфигурация игры стандартна. Мы указываем тип рендерера, размеры холста, цвет фона, ID родительского HTML-элемента и класс нашей сцены.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#000000',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Важно, что backgroundColor задан чёрным (#000000), чтобы контрастно отобразить светлые UI-элементы, созданные в примере. Класс Example, содержащий логику загрузки и создания объектов, передаётся в конфиг как основная сцена.
Что попробовать дальше
9-слайсовые спрайты — это фундаментальный инструмент для построения гибкого и визуально приятного игрового интерфейса в Phaser. Они позволяют отделить логику размеров UI от его художественного оформления.
**Идеи для экспериментов:**
1. Попробуйте динамически менять размер объекта nineslice после его создания через свойства .width и .height. Объект должен плавно перерисовываться.
2. Создайте интерактивную кнопку, которая меняет фрейм (например, на 'pressed') при нажатии, используя тот же принцип 9-слайса.
3. Поэкспериментируйте с подготовкой собственного атласа в редакторе, который поддерживает экспорт данных о 9-слайсе (например, в Unity или специальных программах для упаковки текстур).
