О чем этот пример

Когда вы создаете игры, иногда возникает необходимость «прочитать» цвет конкретного пикселя на изображении. Это может быть полезно для создания интерактивных палитр, детекции столкновений на основе цвета или реализации механик, где игрок взаимодействует с определенными участками текстуры. В этой статье мы разберем, как работает метод `textures.getPixel` в 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('wheel', 'assets/pics/color-wheel.png');
    }

    create ()
    {
        //  578 x 550 (289 x 275)
        this.add.image(400, 300, 'wheel');

        const graphics = this.add.graphics({ x: 0, y: 0 });

        const _this = this;

        this.input.on('pointermove', pointer =>
        {

            const color = _this.textures.getPixel(pointer.x - 111, pointer.y - 25, 'wheel');

            graphics.clear();

            if (color)
            {
                graphics.lineStyle(1, 0x000000, 1);
                graphics.strokeRect(pointer.x - 1, pointer.y - 1, 34, 34);

                graphics.fillStyle(color.color, 1);
                graphics.fillRect(pointer.x, pointer.y, 32, 32);
            }
        });
    }
}

const config = {
    type: Phaser.WEBGL,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    scene: Example
};

const game = new Phaser.Game(config);

Загрузка ресурсов и отображение изображения

Вся работа начинается в методе preload. Здесь мы загружаем текстуру, с которой будем работать. Для этого используется метод this.load.image с указанием ключа и пути к файлу.

this.load.image('wheel', 'assets/pics/color-wheel.png');

После загрузки, в методе create, изображение добавляется на сцену как обычный спрайт. Обратите внимание, что координаты (400, 300) – это центр сцены размером 800x600 пикселей.

this.add.image(400, 300, 'wheel');

Также создается объект graphics – графический контекст для отрисовки примитивов (прямоугольников, линий) поверх сцены. Он будет использоваться для визуализации результата.

Обработка движения указателя и получение цвета

Ключевая логика привязана к событию движения курсора мыши (или пальца на сенсорном экране) pointermove. Каждый раз при движении указателя вызывается переданная функция.

this.input.on('pointermove', pointer => {
    // ... логика обработки
});

Внутри функции первым делом вызывается метод this.textures.getPixel. Он принимает три аргумента: координаты X и Y на самой текстуре и ключ текстуры. Важный нюанс: координаты передаются относительно верхнего левого угла изображения, а не всей сцены. В примере есть смещение (-111 и -25), которое компенсирует позицию изображения на сцене.

const color = _this.textures.getPixel(pointer.x - 111, pointer.y - 25, 'wheel');

Метод возвращает объект Color или null, если координаты выходят за пределы текстуры или пиксель полностью прозрачен.

Визуализация результата

Получив объект color, мы можем его использовать. Перед каждой отрисовкой предыдущие графические примитивы очищаются методом graphics.clear().

graphics.clear();

Если цвет получен (т.е. color не null), мы сначала рисуем черную рамку.

graphics.lineStyle(1, 0x000000, 1);
graphics.strokeRect(pointer.x - 1, pointer.y - 1, 34, 34);

Затем заливаем внутренний квадрат цветом, который получили из текстуры. Свойство color.color содержит числовое представление цвета (например, 0xff00ff), которое напрямую передается в fillStyle.

graphics.fillStyle(color.color, 1);
graphics.fillRect(pointer.x, pointer.y, 32, 32);

В итоге под курсором появляется квадрат, цвет которого точно соответствует пикселю на текстуре в этой точке.

Конфигурация игры и запуск

Пример завершается стандартной конфигурацией игры Phaser. Здесь определяется тип рендерера, элемент-контейнер, размеры холста и главный класс сцены.

const config = {
    type: Phaser.WEBGL,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    scene: Example
};

const game = new Phaser.Game(config);

Использование Phaser.WEBGL обеспечивает аппаратное ускорение графики. Ключ parent должен соответствовать id HTML-элемента на вашей странице.

Что попробовать дальше

Метод textures.getPixel – это мощный инструмент для точного взаимодействия с графикой на уровне пикселей. В рассмотренном примере он используется для создания простой пипетки. Вы можете экспериментировать с этой механикой: например, создать игру, где нужно кликать только на области определенного цвета, реализовать динамическую маску или систему «волшебной кисти», которая меняет свой цвет в зависимости от фона. Помните, что для корректной работы метода важно точно рассчитать смещение координат, если текстура отображается не в начале сцены.