О чем этот пример
При создании интерактивных игровых объектов часто требуется, чтобы игрок мог взаимодействовать не со всем спрайтом, а только с его видимой частью. Особенно это важно для объектов сложной формы, например, масок или иконок с прозрачным фоном. Встроенная система интерактивности Phaser по умолчанию реагирует на клик по прямоугольной области (Bounding Box) спрайта. Эта статья покажет, как использовать опцию `pixelPerfect` для точной проверки попадания по альфа-каналу пикселя, что открывает возможности для создания более сложной и отзывчивой игровой логики.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.atlas('megaset', 'assets/atlas/megaset-0.png', 'assets/atlas/megaset-0.json');
}
create ()
{
const sprite = this.add.sprite(400, 300, 'megaset', 'mask-test2').setInteractive({ pixelPerfect: true });
const text = this.add.text(10, 10, 'Click. Only the black areas should re-act.', { font: '16px Courier', fill: '#000000' });
this.input.on('pointerdown', () =>
{
text.setText('');
});
sprite.on('pointerdown', (pointer, x, y, event) =>
{
text.setText('Sprite Alpha clicked');
event.stopPropagation();
});
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#efefef',
scene: Example
};
const game = new Phaser.Game(config);
Суть Pixel Perfect
Когда вы добавляете интерактивность спрайту через setInteractive(), Phaser создает для него невидимую область (хитбокс), которая по умолчанию соответствует его прямоугольным габаритам. Это значит, что клик в любой точке этого прямоугольника будет считаться попаданием, даже если пиксель в этой точке прозрачный.
Опция pixelPerfect: true меняет это поведение. Она включает проверку альфа-канала конкретного кадра (frame) текстуры в точке клика. Если альфа-канал пикселя равен 0 (полностью прозрачный), событие не срабатывает. Это позволяет сделать кликабельной только непрозрачную часть изображения.
const sprite = this.add.sprite(400, 300, 'megaset', 'mask-test2').setInteractive({ pixelPerfect: true });
Загрузка ресурсов и настройка сцены
В примере используется атлас текстур — эффективный способ хранения множества изображений в одном файле. Метод this.load.atlas() загружает PNG-изображение и соответствующую ему JSON-карту с координатами кадров.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.atlas('megaset', 'assets/atlas/megaset-0.png', 'assets/atlas/megaset-0.json');
}
Конфигурация игры стандартна. Обратите внимание, что фон сцены (backgroundColor: '#efefef') светлый, чтобы черные пиксели спрайта были хорошо видны.
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#efefef',
scene: Example
};
const game = new Phaser.Game(config);
Обработка событий ввода
В примере реализована простая демонстрация работы pixelPerfect. Создается текстовый элемент, который обнуляется при клике в любом месте сцены. Однако, если клик происходит по непрозражному (черному) пикселю спрайта, срабатывает его собственный обработчик, который выводит другое сообщение и останавливает дальнейшее распространение события с помощью event.stopPropagation().
this.input.on('pointerdown', () =>
{
text.setText('');
});
sprite.on('pointerdown', (pointer, x, y, event) =>
{
text.setText('Sprite Alpha clicked');
event.stopPropagation();
});
Таким образом, при клике по прозрачной области спрайта (но в пределах его прямоугольника) сработает только первый обработчик, очищающий текст. Клик по черной области вызовет второй обработчик и покажет сообщение 'Sprite Alpha clicked'.
Важные нюансы и производительность
Использование pixelPerfect требует дополнительных вычислений: для определения попадания движок должен получить данные о пикселе из текстуры. Это может сказаться на производительности, особенно если на сцене много интерактивных объектов или проверки происходят часто (например, в событии pointermove).
- **Используйте для ключевых объектов:** Лучше применять эту опцию для наиболее важных или небольших по размеру спрайтов.
- **Альтернативы для сложных форм:** Для объектов очень сложной формы иногда эффективнее использовать несколько простых геометрических зон (setHitArea) или физические тела.
- **Работает только с POINTER событиями:** Опция актуальна для событий мыши и касаний (pointerdown, pointerup, pointerover и т.д.).
Что попробовать дальше
Опция pixelPerfect — мощный инструмент для тонкой настройки интерактивности в Phaser. Она незаменима при создании интерфейсов со сложными иконками, интерактивных масок или игровых объектов, форма которых критична для геймплея (например, пазлы).
**Идеи для экспериментов:**
1. Создайте спрайт-кнопку в виде звезды и сделайте ее отзывчивой только по контуру.
2. Реализуйте механику "вырезания" объекта из фона, где кликабельна только его внутренняя часть.
3. Сравните производительность: добавьте 50 интерактивных спрайтов с pixelPerfect и без, перемещая курсор над ними.
