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

Визуальное оформление текста — ключевой элемент геймдизайна. Статичные надписи могут выглядеть скучно, особенно в играх с ярким художественным стилем. В этой статье мы разберем, как использовать нативное API Canvas для создания текста с плавным градиентом прямо в 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('lulu', 'assets/pics/shocktroopers-lulu2.png');
    }

    create ()
    {
        this.add.image(790, 600, 'lulu').setOrigin(1);

        const text = this.add.text(25, 250, 'Gradient', { fontFamily: 'Arial Black', fontSize: 82 });
        text.setStroke('#000000', 4);

        //  Apply the gradient fill.
        const gradient = text.context.createLinearGradient(0, 0, 0, text.height);
        gradient.addColorStop(0, '#111111');
        gradient.addColorStop(0.5, '#ffffff');
        gradient.addColorStop(0.5, '#aaaaaa');
        gradient.addColorStop(1, '#111111');

        text.setFill(gradient);

    }
}

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

const game = new Phaser.Game(config);

Подготовка сцены и загрузка ассетов

Работа начинается в методе preload() нашей сцены. Здесь мы устанавливаем базовый URL для загрузки и загружаем фоновое изображение. Это стандартный подход в Phaser для подготовки ресурсов.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('lulu', 'assets/pics/shocktroopers-lulu2.png');
}

Создание базового текстового объекта

В методе create() мы сначала добавляем фоновое изображение для контекста. Затем создаем основной текстовый объект с помощью this.add.text(). Важно задать достаточно большой fontSize и жирный шрифт, чтобы градиент был хорошо заметен. Сразу же применяем черную обводку (setStroke), чтобы буквы лучше читались на любом фоне.

create ()
{
    this.add.image(790, 600, 'lulu').setOrigin(1);

    const text = this.add.text(25, 250, 'Gradient', { fontFamily: 'Arial Black', fontSize: 82 });
    text.setStroke('#000000', 4);
}

Работа с Canvas Context и создание градиента

Это ключевой этап. Каждый текстовый объект Phaser при использовании рендерера Canvas имеет свойство context — это прямой доступ к нативному CanvasRenderingContext2D. Мы используем его метод createLinearGradient().

Параметры (x0, y0, x1, y1) задают линию, вдоль которой будет растягиваться градиент. В нашем случае (0, 0, 0, text.height) — это вертикальная линия от верхнего до нижнего края текстового блока.

Метод addColorStop(position, color) определяет цвета и их положение на этой линии (от 0 до 1). Обратите внимание на хитрость в примере: два стопа на позиции 0.5 создают резкую границу между белым и серым, что дает сложный визуальный эффект.

//  Apply the gradient fill.
const gradient = text.context.createLinearGradient(0, 0, 0, text.height);
gradient.addColorStop(0, '#111111');
gradient.addColorStop(0.5, '#ffffff');
gradient.addColorStop(0.5, '#aaaaaa');
gradient.addColorStop(1, '#111111');

Применение градиента к тексту

Созданный объект градиента — это обычное значение, которое можно использовать в Canvas. Метод text.setFill() в Phaser принимает не только строку с цветом, но и такой объект CanvasGradient. После его вызова градиент немедленно применяется к заливке текста, заменяя сплошной цвет.

text.setFill(gradient);

Конфигурация игры

Важное ограничение: данный метод работает только с рендерером Phaser.CANVAS. При использовании Phaser.WEBGL свойство context у текстового объекта будет недоступно, и код вызовет ошибку. В конфиге мы явно задаем тип рендерера, размеры, контейнер и цвет фона.

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

const game = new Phaser.Game(config);

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

Использование CanvasRenderingContext2D открывает мощные возможности для кастомизации графики прямо из кода Phaser. Вы можете создавать не только линейные, но и радиальные градиенты, применять их к контуру текста (setStroke) или даже анимировать, пересоздавая градиент каждый кадр. Для экспериментов попробуйте создать горизонтальный градиент, использовать цвета вашей игровой палитры или динамически менять положение цветовых стопов в зависимости от игровых событий, например, для эффекта "зарядки" полоски здоровья.