О чем этот пример
Создание интерактивных визуальных эффектов, реагирующих на цвет игрового мира, — мощный инструмент для разработчика. Пример `snapshotPixel` демонстрирует, как в Phaser 3 можно получить цвет конкретного пикселя на экране в момент клика. Эта техника открывает двери для механик, где игровое окружение напрямую влияет на геймплей: от заклинаний, которые анализируют поверхность, до динамических систем освещения, подстраивающихся под фон. В этой статье мы разберем, как работает этот метод и как его можно применить в ваших проектах.
Версия 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('pym', 'assets/pics/cougar-face-of-nature.png');
this.load.image('logo', 'assets/sprites/phaser3-logo.png');
this.load.image('red', 'assets/particles/red.png');
}
create ()
{
const g = this.add.graphics().setDepth(1);
this.input.on('pointerdown', function (pointer)
{
this.game.renderer.snapshotPixel(pointer.x, pointer.y, pixel =>
{
g.clear();
g.fillStyle(pixel.color);
g.fillRect(0, 0, 128, 128);
});
}, this);
// Everything from here down is just stuff to display, so you can grab from it
const bg = this.add.image(400, 300, 'pym').setScale(3);
bg.texture.setFilter(1);
const particles = this.add.particles(0, 0, 'red', {
speed: 100,
scale: { start: 1, end: 0 },
blendMode: 'ADD'
});
const logo = this.physics.add.image(400, 100, 'logo');
logo.setVelocity(100, 200);
logo.setBounce(1, 1);
logo.setCollideWorldBounds(true);
particles.startFollow(logo);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'phaser-example',
physics: {
default: 'arcade',
arcade: {
gravity: { y: 200 }
}
},
scene: Example
};
const game = new Phaser.Game(config);
Принцип работы snapshotPixel
Метод snapshotPixel принадлежит рендереру игры (this.game.renderer) и позволяет мгновенно получить данные о цвете пикселя по заданным координатам на канвасе. В отличие от создания полного скриншота (snapshot), этот метод легковесен и выполняется синхронно, что делает его идеальным для мгновенной реакции на действия игрока, например, на клик.
Ключевой особенностью является его колбэк-функция, которая получает объект с данными пикселя. В нашем примере этот объект содержит свойство color.
this.game.renderer.snapshotPixel(pointer.x, pointer.y, pixel => {
// pixel.color содержит цвет в формате '#rrggbbaa'
});
Обработка клика и визуализация результата
В примере вызов snapshotPixel привязан к событию указателя 'pointerdown'. При каждом клике мыши передаются координаты клика (pointer.x, pointer.y).
Полученный цвет сразу же используется для отрисовки графики. Созданный заранее объект Graphics (`g`) очищается, ему задается новый стиль заливки, равный считанному цвету, и рисуется квадрат.
const g = this.add.graphics().setDepth(1);
this.input.on('pointerdown', function (pointer) {
this.game.renderer.snapshotPixel(pointer.x, pointer.y, pixel => {
g.clear();
g.fillStyle(pixel.color); // Устанавливаем цвет из пикселя
g.fillRect(0, 0, 128, 128); // Рисуем квадрат этим цветом
});
}, this);
Обратите внимание на контекст this, переданный в метод on. Это необходимо, чтобы внутри колбэка обработчика события оставалась ссылка на экземпляр сцены.
Подготовка сцены: фон, физика и частицы
Вся остальная часть кода в create служит лишь для создания динамичной и красочной сцены, с которой можно взаимодействовать. Это демонстрационный "стенд".
1. **Фон:** Изображение масштабируется и для него отключается сглаживание (setFilter(1)), чтобы цвета были четче.
2. **Система частиц (ParticleEmitter):** Создается эмиттер, испускающий красные частицы, которые следуют за логотипом.
3. **Физический спрайт:** Логотип Phaser добавляется в мир физики Arcade. Ему задается скорость, упругость (setBounce) и включается столкновение с границами мира (setCollideWorldBounds). Именно за этим логотипом и летят частицы.
const bg = this.add.image(400, 300, 'pym').setScale(3);
bg.texture.setFilter(1);
const particles = this.add.particles(0, 0, 'red', {
speed: 100,
scale: { start: 1, end: 0 },
blendMode: 'ADD'
});
const logo = this.physics.add.image(400, 100, 'logo');
logo.setVelocity(100, 200);
logo.setBounce(1, 1);
logo.setCollideWorldBounds(true);
particles.startFollow(logo);
Практическое применение и ограничения
Хотя пример прост, он иллюстрирует основу для более сложных механик: * **Цветовые головоломки:** Игрок должен кликать на объекты определенного цвета. * **Динамические эффекты:** Цвет фона в точке клика может влиять на силу или тип заклинания. * **Инструменты для разработки:** Создание пипетки для выбора цвета прямо из игровой сцены.
Важное ограничение: метод snapshotPixel считывает пиксель с итогового изображения на канвасе, уже после применения всех отрисовок, смешиваний (blendMode) и фильтров. Координаты (pointer.x, pointer.y) — это координаты относительно самого канваса, а не игрового мира. Для преобразования координат мира в координаты камеры (вида) можно использовать this.cameras.main.getWorldPoint().
Что попробовать дальше
Метод snapshotPixel — это ваш прямой доступ к визуальному состоянию игры в реальном времени. Он позволяет создавать глубокую связь между визуальным представлением и игровой логикой. Для экспериментов попробуйте
- Изменить размер и форму отрисовываемого
Graphicsобъекта на основе, например, альфа-канала считанного пикселя - Накопить несколько последних считанных цветов для создания палитры
- Использовать цвет для мгновенного изменения свойств физического тела, в которое попал клик (например, сделать его скорость зависимой от яркости цвета фона)
