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

Вы когда-нибудь сталкивались с тем, что длинный текст в вашей игре на Phaser вылезает за границы экрана или элемента интерфейса? Это распространённая проблема, особенно для локализаций или динамически генерируемых сообщений. К счастью, в Phaser есть встроенный механизм для автоматического переноса слов. В этой статье мы разберём, как правильно его настроить, чтобы текст всегда красиво умещался в отведённое пространство, улучшая читаемость и общий вид вашей игры.

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


class Example extends Phaser.Scene
{
    constructor ()
    {
        super();
    }

    create ()
    {
        var messages = [ 'Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet', 'Test 1', 'Test 2', 'Test 3' ];

        var textStyle = {
            wordWrap: { width: 385, useAdvancedWrap: true }
        };

        var text = this.add.text(0, 0, '', textStyle);

        text.setText(messages.join('\n'));
    }
}

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

const game = new Phaser.Game(config);

Проблема: Текст за пределами экрана

Представьте, что вы создаёте диалоговую систему или информационную панель. Если текстовая строка окажется слишком длинной, она попросту уйдёт за границы вашего игрового мира или контейнера, и игрок не увидит её полностью. В предоставленном примере массив messages содержит как очень длинную строку, так и короткие. Без специальной обработки длинная строка отобразится в одну линию, что явно не то, что нужно.

Именно для решения этой проблемы в объекте TextStyle существует опция wordWrap.

Решение: Настройка объекта wordWrap

Ключ к управлению переносом слов лежит в конфигурации стиля текста. Вместо того чтобы передавать простую строку стиля (например, { fontSize: '16px' }), мы создаём объект с вложенным свойством wordWrap.

var textStyle = {
    wordWrap: { width: 385, useAdvancedWrap: true }
};

Здесь мы определяем два параметра: 1. width: 385 — Это максимальная ширина в пикселях, которую может занимать одна строка текста. Как только текст достигает этой границы, происходит перенос. 2. useAdvancedWrap: true — Этот флаг включает более интеллектуальный алгоритм переноса, который корректно обрабатывает пробелы и стремится разбивать строки по границам слов, а не просто по достижении лимита символов.

Этот объект стиля затем передаётся третьим аргументом в метод this.add.text().

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

Теперь создадим сам текстовый объект, используя подготовленный стиль.

var text = this.add.text(0, 0, '', textStyle);

Мы указываем начальные координаты (0, 0), пустую начальную строку и наш стиль textStyle. Важно сначала создать объект с правильными настройками, а уже потом наполнять его контентом.

Для установки текста используем метод setText(). В примере все строки из массива объединяются в одну с помощью join('\n'), где '\n' — символ новой строки. Это означает, что каждая строка массива станет новым абзацем, и к каждой из них (в частности, к длинной первой) будет применено правило переноса.

text.setText(messages.join('\n'));

Как это работает на практике

После запуска примера вы увидите, что длинная строка "Lorem ipsum..." разбита на несколько строк. Каждая из этих строк не превышает заданную ширину в 385 пикселей. Короткие строки "Test 1", "Test 2" и "Test 3" остаются в одну строку, так как они и так умещаются в лимит.

Механизм переноса работает в реальном времени. Если вы динамически измените текст с помощью setText(), новый контент также будет автоматически отформатирован согласно правилам wordWrap. Это особенно полезно для обновляемого текста, например, логов событий или подсказок.

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

Использование wordWrap — это простой и мощный способ контролировать вёрстку текста в ваших играх на Phaser. Он избавляет от необходимости вручную разбивать строки и делает интерфейс более адаптивным. **Идеи для экспериментов:** 1. Попробуйте менять значение width в процессе игры, чтобы текст динамически подстраивался под изменяющиеся размеры панели. 2. Поэкспериментируйте с useAdvancedWrap: false и посмотрите, как изменится поведение переноса. 3. Скомбинируйте перенос слов с другими свойствами TextStyle, такими как align (выравнивание) или lineSpacing (межстрочный интервал), для создания сложных текстовых блоков.