О чем этот пример
При разработке игр часто возникает задача сделать спрайт интерактивным — чтобы он реагировал на наведение курсора. Но что, если ваш спрайт имеет сложную форму с прозрачными областями? Обычный прямоугольный хитбокс будет срабатывать даже при наведении на пустые пиксели, что выглядит неряшливо. В этой статье мы разберем, как использовать опцию `pixelPerfect` в Phaser для создания точного, пиксельного определения попадания, которое учитывает альфа-канал изображения. Это значительно улучшит пользовательский опыт, особенно в казуальных играх или интерфейсах с иконками сложной формы.
Версия 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.image('hello', 'assets/sprites/hello.png');
}
create ()
{
const sprite = this.add.sprite(400, 300, 'hello').setInteractive({ pixelPerfect: true });
sprite.on('pointerover', function ()
{
this.setTint(0xff0000);
});
sprite.on('pointerout', function ()
{
this.setTint();
});
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#efefef',
scene: Example
};
const game = new Phaser.Game(config);
Проблема прямоугольного хитбокса
По умолчанию, когда вы делаете игровой объект интерактивным с помощью .setInteractive(), Phaser создает для него хитбокс в форме прямоугольника, равного размеру текстуры. Это быстро и эффективно для вычислений, но создает проблемы визуального восприятия.
Представьте спрайт в форме звезды или надписи с закругленными буквами. Прямоугольная область, в которую он вписан, будет включать в себя много прозрачных пикселей по углам. Игрок будет видеть, как курсор меняет состояние (например, на указатель), наводя его на пустое пространство вокруг спрайта. Это ломает immersion и выглядит как баг.
// Стандартный вызов создает прямоугольный хитбокс
sprite.setInteractive();
Решение: Включение Pixel Perfect
Phaser предоставляет элегантное решение — опцию pixelPerfect в конфигурационном объекте метода .setInteractive(). Когда эта опция установлена в true, система взаимодействия начинает проверять не просто попадание в прямоугольник, а конкретно в непрозрачные пиксели текстуры спрайта.
Внутренний механизм работает так: при событии взаимодействия (например, pointerover) Phaser берет координаты курсора, переводит их в координаты текстуры спрайта и проверяет альфа-значение (прозрачность) пикселя в этой позиции. Если пиксель непрозрачен (альфа > 0), событие срабатывает. Если пиксель прозрачен — событие игнорируется.
// Включение точного пиксельного проверки попадания
const sprite = this.add.sprite(400, 300, 'hello').setInteractive({ pixelPerfect: true });
Обработка событий Pointerover и Pointerout
С включенным pixelPerfect логика обработки событий становится интуитивно правильной. Мы можем повесить обработчики на события pointerover (курсор нашел непрозрачный пиксель) и pointerout (курсор покинул все непрозрачные пиксели).
В предоставленном примере при наведении спрайт окрашивается в красный оттенок с помощью метода .setTint(). Когда курсор уходит, оттенок снимается вызовом того же метода без аргументов.
Важно помнить, что контекст (this) внутри функций-обработчиков, переданных в .on(), будет ссылаться на сам спрайт, к которому привязано событие. Это позволяет легко модифицировать его свойства.
sprite.on('pointerover', function () {
// 'this' здесь — это спрайт 'sprite'
this.setTint(0xff0000); // Применяем красный оттенок
});
sprite.on('pointerout', function () {
this.setTint(); // Сбрасываем оттенок
});
Производительность и ограничения
Использование pixelPerfect — это компромисс между точностью и производительностью. Пиксельная проверка требует больше вычислений, чем простая проверка прямоугольника. Для одного-двух спрайтов на сцене разница незаметна, но если сделать десятки или сотни мелких интерактивных объектов с такой опцией, это может повлиять на частоту кадров, особенно на мобильных устройствах.
Рекомендации по использованию:
* Применяйте для ключевых, крупных или сложных по форме объектов (персонажи, большие кнопки, иконки).
* Избегайте для множества мелких, часто обновляемых объектов (например, частиц).
* Для простых геометрических форм (квадраты, круги) достаточно стандартного хитбокса или хитбокса, заданного вручную через setInteractive(shape, callback).
Опция идеально подходит для статичных или малоподвижных элементов UI и важных игровых предметов, где точность взаимодействия критична.
Что попробовать дальше
Опция pixelPerfect: true — это мощный инструмент для повышения качества взаимодействия в вашей игре. Она позволяет спрайтам реагировать на курсор ровно так, как видит игрок, исключая ложные срабатывания на прозрачных областях. Для экспериментов попробуйте применить этот подход к анимированному спрайту (с pixelPerfect на каждом кадре анимации) или создайте сложную интерактивную карту, где разные области одного большого изображения реагируют по-разному. Помните о балансе между точностью и производительностью, и ваши игры станут заметно приятнее и профессиональнее.
