О чем этот пример
При разработке игр для веба вы не можете быть на 100% уверены, что у пользователя установлен нужный шрифт. Если указанного шрифта нет в системе, браузер либо использует стандартный (часто некрасивый), либо вовсе не отображает текст. Это может испортить дизайн интерфейса или сделать текст нечитаемым. В этой статье мы разберем простой, но эффективный прием — задание резервных (fallback) шрифтов для текстовых объектов в Phaser, который гарантирует, что ваш текст всегда будет корректно показан.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
this.add.text(100, 100, 'Hello World', { fontFamily: 'Verdana, "Times New Roman", Tahoma, serif', fontSize: 64, color: '#ffffff' });
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Проблема: шрифты в вебе ненадежны
В отличие от настольных игр, веб-игра запускается в среде браузера, которая сильно зависит от операционной системы и настроек пользователя. Если вы укажете в Phaser шрифт 'SomeFancyFont', а его не окажется на компьютере игрока, браузер не сможет его загрузить автоматически (если это не веб-шрифт). В результате текст может быть отображен не тем семейством шрифтов, которое вы задумывали, что ломает визуальную гармонию.
Phaser не управляет загрузкой системных шрифтов. Он передает ваши настройки напрямую в Canvas или WebGL контекст браузера, который и занимается рендерингом. Поэтому ответственность за корректное отображение лежит на вас, разработчике.
Решение: указание списка шрифтов через запятую
Стандартный CSS-подход к этой проблеме — указание нескольких шрифтов через запятую в свойстве font-family. Браузер будет пытаться использовать их по порядку слева направо, пока не найдет первый доступный в системе.
В Phaser этот список передается в свойстве fontFamily объекта стилей текста. Синтаксис полностью соответствует CSS.
Давайте посмотрим на код из примера:
Разбор примера кода
В методе create() сцены создается текстовый объект. Ключевой момент — свойство fontFamily в третьем аргументе (объекте стилей).
this.add.text(100, 100, 'Hello World', {
fontFamily: 'Verdana, "Times New Roman", Tahoma, serif',
fontSize: 64,
color: '#ffffff'
});
**Как это работает:** 1. Браузер пытается найти и использовать шрифт **Verdana** (распространен в Windows). 2. Если Verdana недоступна, он переходит к **Times New Roman** (есть в Windows и macOS). Имя из двух слов взято в кавычки. 3. Если и его нет, пробует **Tahoma** (также распространенный шрифт). 4. В крайнем случае используется общее семейство **serif** (шрифт с засечками). Браузер сам выберет любой доступный шрифт из этой категории.
Таким образом, мы прошли путь от конкретного предпочтительного шрифта к общему гарантированному семейству.
Правила оформления списка шрифтов
При формировании строки fontFamily следуйте простым правилам:
- Разделяйте названия шрифтов запятой.
- Названия, состоящие из нескольких слов (например, Times New Roman, Courier New), заключайте в кавычки. В JavaScript строку внутри строки удобно экранировать обратным слэшем: "Times New Roman".
- Последним элементом списка всегда указывайте общее семейство. Это ваша страховка. Основные семейства: serif, sans-serif, monospace, cursive, fantasy.
- Порядок имеет значение. Ставьте самый желаемый шрифт первым.
Пример с веб-безопасным шрифтом Arial и страховкой:
// Хорошо: Arial, потом общее семейство sans-serif
this.add.text(200, 300, 'Score: 1000', {
fontFamily: 'Arial, sans-serif',
fontSize: 32
});
Практические рекомендации
1. **Используйте веб-безопасные шрифты в начале списка.** Это шрифты, которые с высокой вероятностью есть на большинстве систем (Arial, Verdana, Tahoma, Georgia, Courier New, Times New Roman).
2. **Тестируйте на разных ОС.** Запустите игру на Windows, macOS, Linux или попросите коллег проверить. Убедитесь, что текст выглядит приемлемо при использовании резервных вариантов.
3. **Для нестандартных шрифтов используйте веб-шрифты.** Если вам критически важен уникальный шрифт (для брендинга или атмосферы), загрузите его файлы в проект и подключите через CSS. Тогда в fontFamily можно будет указать только его название, так как вы гарантируете его наличие.
4. **Учитывайте разницу в рендеринге.** Даже если шрифты с засечками (serif) и без (sans-serif) отобразят текст, их метрики (ширина символов, высота) могут отличаться. Это может сдвинуть или "поломать" верстку вашего интерфейса. Проектируйте интерфейсы с небольшим запасом.
Что попробовать дальше
Использование списка резервных шрифтов — это базовый, но обязательный прием для создания надежных и кросс-платформенных игр на Phaser. Он требует минимум усилий, но страхует от неприятных сюрпризов для игроков.
**Идеи для экспериментов:**
1. Создайте сцену-тест, которая выводит один и тот же текст несколькими способами: с идеальным шрифтом, с резервным списком и только с общим семейством. Сравните результат.
2. Попробуйте задать для разных элементов интерфейса (заголовок, основной текст, цифры счетчика) разные приоритетные шрифты, но с одинаковым конечным семейством (например, sans-serif), чтобы сохранить единый стиль в любом случае.
3. Исследуйте, как влияет выбор monospace для отображения внутриигрового кода или чисел в таблице рекордов.
