О чем этот пример
Работа с динамическими текстурами открывает широкие возможности для создания интерактивных визуальных эффектов. Часто в играх требуется реагировать на взаимодействие с графикой: например, определять цвет, на который кликнул игрок, для создания палитр, пипеток или систем раскрашивания. В этой статье мы разберем, как создать динамическую текстуру из изображения и программно получить цвет конкретного пикселя по координатам клика. Этот подход полезен для реализации механик, где цветовая информация важна для геймплея.
Версия 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.image('wheel', 'assets/pics/large-color-wheel.png');
}
create ()
{
const texture = this.textures.addDynamicTexture('wheelTexture', 800, 600)
// Draw the color wheel to our texture
texture.stamp('wheel', null, 400, 300).render();
// Now add the finished texture to a Sprite
this.add.sprite(400, 300, 'wheelTexture');
// Add a Rectangle so we can show the color we've grabbed
const rect = this.add.rectangle(10, 10, 128, 128, 0xffffff).setOrigin(0, 0);
const callback = (color) => {
rect.setFillStyle(color.color);
};
this.input.on('pointerdown', pointer => {
texture.snapshotPixel(pointer.worldX, pointer.worldY, callback);
});
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#2d2d6d',
scene: Example
};
const game = new Phaser.Game(config);
Создание динамической текстуры и ее отрисовка
Динамическая текстура в Phaser — это текстура, создаваемая и управляемая во время выполнения программы, в отличие от загруженных из файлов. Она ведет себя как обычная текстура, но ее содержимое можно изменять.
В методе create сцены мы создаем такую текстуру с помощью метода this.textures.addDynamicTexture. Ей нужно указать уникальный ключ, ширину и высоту.
const texture = this.textures.addDynamicTexture('wheelTexture', 800, 600)
Затем мы используем метод stamp, чтобы отпечатать на этой динамической текстуре заранее загруженное изображение с ключом 'wheel'. Параметры метода позволяют указать источник, фрейм и координаты (x, y) для позиционирования. После выполнения операции stamp необходимо вызвать render(), чтобы изменения были применены к текстуре.
texture.stamp('wheel', null, 400, 300).render();
Теперь текстуру можно использовать как обычную. Мы создаем спрайт, который будет отображать наше сгенерированное изображение.
this.add.sprite(400, 300, 'wheelTexture');
Также мы заранее создаем белый прямоугольник, который позже будет менять цвет, чтобы визуализировать выбранный пиксель.
const rect = this.add.rectangle(10, 10, 128, 128, 0xffffff).setOrigin(0, 0);
Получение цвета пикселя по клику
Основная задача — получить цвет пикселя в текстуре по координатам указателя мыши. Для этого в Phaser у динамической текстуры есть метод snapshotPixel. Этот метод асинхронно считывает данные цвета.
Мы подписываемся на событие клика (pointerdown) у системного ввода this.input. В обработчике события мы получаем объект pointer, который содержит координаты клика в мире игры (pointer.worldX, pointer.worldY).
this.input.on('pointerdown', pointer => {
texture.snapshotPixel(pointer.worldX, pointer.worldY, callback);
});
Метод snapshotPixel принимает три аргумента:
1. Координата X точки в текстуре.
2. Координата Y точки в текстуре.
3. Функция обратного вызова (callback), которая будет выполнена, когда цвет будет готов.
Важно понимать, что координаты должны соответствовать координатам в текстуре (и в мире игры в нашем случае, так как спрайт и камера находятся в одной системе).
Обработка результата и визуализация
Функция обратного вызова получает объект color с информацией о цвете. В нашем примере мы заранее определили эту функцию как callback. Она принимает один параметр, который мы назвали color.
const callback = (color) => {
rect.setFillStyle(color.color);
};
Объект color содержит несколько свойств, но для изменения заливки прямоугольника нам нужно свойство color.color. Это числовое значение цвета в формате, понятном для Phaser (например, 0xff00ff).
Метод setFillStyle у графического объекта Rectangle применяет этот цвет, мгновенно меняя внешний вид прямоугольника на выбранный цвет из текстуры. Таким образом, интерфейс дает игроку немедленную обратную связь.
rect.setFillStyle(color.color);
Конфигурация игры и запуск
Код примера завершается стандартной для Phaser 3 конфигурацией и созданием экземпляра игры. Обратите внимание на размеры сцены (800x600) и цвет фона (#2d2d6d).
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#2d2d6d',
scene: Example
};
const game = new Phaser.Game(config);
Размеры сцены совпадают с размерами создаваемой динамической текстуры (800x600), что гарантирует корректное соответствие координат.
Что попробовать дальше
Использование snapshotPixel для динамических текстур — мощный инструмент для создания интерактивных элементов, связанных с цветом. Вы можете расширить этот пример, чтобы создавать полноценные пипетки в играх-раскрасках, проверять, попал ли игрок в область определенного цвета в головоломках, или динамически генерировать цветовые схемы на основе игрового мира. Попробуйте применить этот метод к нескольким текстурам или сохранять массив выбранных цветов для создания пользовательской палитры.
