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

Стандартный набор шрифтов в браузере ограничен и часто не подходит для создания уникальной атмосферы игры. В этой статье мы разберем пример из официального репозитория Phaser, который показывает, как динамически загружать и использовать шрифты с Google Fonts прямо в игре. Этот подход позволяет легко экспериментировать со стилями текста, создавая эффектные заголовки, диалоги или элементы интерфейса, не добавляя файлы шрифтов в проект. Это особенно полезно для прототипирования и небольших игр, где важна скорость разработки и визуальная выразительность.

Версия 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('bg', 'assets/skies/gradient28.png');
        this.load.script('webfont', 'https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js');
    }

    create ()
    {
        this.add.image(400, 300, 'bg');

        const add = this.add;
        const input = this.input;

        WebFont.load({
            google: {
                families: [ 'Freckle Face', 'Finger Paint', 'Nosifer' ]
            },
            active: function ()
            {
                add.text(16, 0, 'The face of the\nmoon was in\nshadow.', { fontFamily: 'Freckle Face', fontSize: 80, color: '#ffffff' }).setShadow(2, 2, '#333333', 2, false, true);
                add.text(250, 450, 'Waves flung themselves\nat the blue evening.', { fontFamily: 'Finger Paint', fontSize: 40, color: '#5656ee' });

                const t = add.text(330, 200, 'R.I.P', { fontFamily: 'Nosifer', fontSize: 150, color: '#ff3434' });

                input.once('pointerdown', () =>
                {
                    t.setFontSize(64);
                });
            }
        });
    }
}

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

const game = new Phaser.Game(config);

Подготовка: загрузка ресурсов и скрипта WebFont

Вся подготовка происходит в методе preload(). Сначала устанавливается базовый URL для загрузки изображений из репозитория с примерами, а затем загружается фоновое изображение.

Ключевой момент — загрузка стороннего скрипта webfont.js с помощью метода load.script(). Этот скрипт от Google предоставляет удобный API для динамической подгрузки веб-шрифтов прямо в браузер.

this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/skies/gradient28.png');
this.load.script('webfont', 'https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js');

Загрузка и применение шрифтов

Метод create() отвечает за создание сцены. Сначала добавляется фоновое изображение. Далее, для удобства, создаются локальные ссылки на менеджер объектов this.add и систему ввода this.input.

Затем вызывается функция WebFont.load(), которая стала доступна после загрузки скрипта в preload(). В её конфигурационном объекте указываются названия семейств шрифтов, которые нужно загрузить из Google Fonts.

WebFont.load({
    google: {
        families: [ 'Freckle Face', 'Finger Paint', 'Nosifer' ]
    },
    active: function ()
    {
        // Создание текста произойдет здесь, после загрузки шрифтов
    }
});

Колбэк active выполняется только после того, как все указанные шрифты будут полностью загружены и готовы к использованию. Всю работу по созданию текстовых объектов нужно помещать внутрь этого колбэка, иначе браузер применит шрифт по умолчанию.

Создание текстовых объектов с разными стилями

Внутри колбэка active создаются три текстовых объекта, каждый со своим уникальным шрифтом, размером и цветом. Здесь используется объект add, сохраненный ранее.

Первый текст использует метод .setShadow() для добавления тени с заданным смещением, цветом и размытием. Второй текст демонстрирует использование переноса строк через \n. Обратите внимание, что свойство fontFamily в стиле текста должно точно соответствовать названию, указанному в массиве families.

add.text(16, 0, 'The face of the\nmoon was in\nshadow.', { fontFamily: 'Freckle Face', fontSize: 80, color: '#ffffff' }).setShadow(2, 2, '#333333', 2, false, true);
add.text(250, 450, 'Waves flung themselves\nat the blue evening.', { fontFamily: 'Finger Paint', fontSize: 40, color: '#5656ee' });

Интерактивность: изменение свойств текста

Пример также показывает, как сделать текст интерактивным. Третий текстовый объект сохраняется в константу `t. Затем на событие однократного нажатия указателя (pointerdown) вешается обработчик. При клике по сцене размер шрифта этого текстового объекта меняется с 150 на 64 пикселя с помощью методаsetFontSize()`.

const t = add.text(330, 200, 'R.I.P', { fontFamily: 'Nosifer', fontSize: 150, color: '#ff3434' });

input.once('pointerdown', () =>
{
    t.setFontSize(64);
});

Этот паттерн можно использовать для создания кнопок, анимированных заголовков или скрывающихся подсказок.

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

Использование Google Fonts через WebFont Loader — это быстрый и эффективный способ добавить в игру разнообразную типографику. Основное преимущество — не нужно хранить файлы шрифтов локально. Однако для production-проектов стоит рассмотреть возможность самостоятельного хостинга шрифтов для гарантии их доступности и контроля за производительностью. Для экспериментов попробуйте: изменить шрифты в списке families на другие с Google Fonts; анимировать изменение цвета текста или его позиции; создать меню, где каждый пункт использует разный загруженный шрифт.