О чем этот пример
Корректное отображение текста — ключевая часть интерфейса любой игры. Когда текст выходит за границы элемента или экрана, он становится нечитаемым и портит впечатление. Phaser предлагает встроенную систему переноса текста по ширине, которая работает в двух режимах: базовом и расширенном (`useAdvancedWrap`). Эта статья покажет, как легко управлять переносом текста в вашем проекте, чтобы диалоги, описания и интерфейс всегда выглядели аккуратно.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
// Basic text wrapping based on width.
this.make.text({
x: 400,
y: 100,
text: 'The sky above the port was the color of television, tuned to a dead channel.',
origin: { x: 0.5, y: 0.5 },
style: {
font: 'bold 25px Arial',
fill: 'white',
wordWrap: { width: 300 }
}
});
// Basic wrap will NOT touch the whitespace in your text.
this.make.text({
x: 400,
y: 250,
text: ' Basic wrapping: look at all this weird space ',
origin: { x: 0.5, y: 0.5 },
style: {
font: 'bold 25px Arial',
fill: 'white',
wordWrap: { width: 300 }
}
});
// Advanced wrap will collapse neighboring spaces into a single space and trim whitespace from
// the start and end of each line.
this.make.text({
x: 400,
y: 375,
text: ' Advanced wrapping: space collapses and is trimmed ',
origin: { x: 0.5, y: 0.5 },
style: {
font: 'bold 25px Arial',
fill: 'white',
wordWrap: { width: 300, useAdvancedWrap: true }
}
});
// The advanced word wrapping algorithm will also break words that are longer than the specified
// wrap width
this.make.text({
x: 400,
y: 500,
text: 'Long word incoming: Supercalifragilisticexpialidocious!',
origin: { x: 0.5, y: 0.5 },
style: {
font: 'bold 25px Arial',
fill: 'white',
wordWrap: { width: 300, useAdvancedWrap: true }
}
});
}
}
const config = {
type: Phaser.CANVAS,
width: 800,
height: 600,
backgroundColor: '#0072bc',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Создание текста с базовым переносом
Базовый перенос — это самый простой способ ограничить ширину текстового блока. Вы указываете максимальную ширину (width) в пикселях, и движок автоматически разбивает строку, когда она превышает этот лимит. Разрыв происходит только по границам слов (пробелам).
Обратите внимание, что базовый перенос не изменяет исходный текст. Все пробелы, включая лишние в начале, середине или конце строки, остаются на своих местах. Это может привести к неожиданным отступам.
this.make.text({
x: 400,
y: 100,
text: 'The sky above the port was the color of television, tuned to a dead channel.',
origin: { x: 0.5, y: 0.5 },
style: {
font: 'bold 25px Arial',
fill: 'white',
wordWrap: { width: 300 } // Базовый перенос на ширину 300px
}
});
Ограничение базового переноса
Базовый режим не обрабатывает лишние пробелы. Если в вашем тексте много пробелов подряд, они будут отображены как есть, что может испортить визуальное выравнивание.
В примере ниже текст содержит множество пробелов. Базовый перенос разобьёт строку по ширине, но все эти пробелы останутся видимыми, создавая странные отступы в начале строк и между словами.
this.make.text({
x: 400,
y: 250,
text: ' Basic wrapping: look at all this weird space ',
origin: { x: 0.5, y: 0.5 },
style: {
font: 'bold 25px Arial',
fill: 'white',
wordWrap: { width: 300 } // Пробелы сохраняются
}
});
Расширенный перенос с useAdvancedWrap
Для более «интеллектуальной» обработки текста используйте расширенный режим, активируемый флагом useAdvancedWrap: true. Этот режим выполняет предварительную очистку текста: он обрезает пробелы в начале и конце каждой итоговой строки, а также заменяет несколько идущих подряд пробелов на один.
Это идеально подходит для текста, который может быть загружен из внешнего источника (например, файла локализации) и содержать непреднамеренное форматирование.
this.make.text({
x: 400,
y: 375,
text: ' Advanced wrapping: space collapses and is trimmed ',
origin: { x: 0.5, y: 0.5 },
style: {
font: 'bold 25px Arial',
fill: 'white',
wordWrap: { width: 300, useAdvancedWrap: true } // Пробелы схлопнутся и обрежутся
}
});
Перенос слишком длинных слов
Ещё одно ключевое преимущество расширенного режима — умение разбивать слишком длинные слова, которые не помещаются в заданную ширину. Базовый перенос оставит такое слово целиком на одной строке, что нарушит ограничение по ширине.
Расширенный алгоритм принудительно разрывает длинное слово по символам, чтобы оно вписалось в лимит width. Это критически важно для интерфейсов с динамическим текстом, где вы не можете заранее проверить длину всех слов (например, имена игроков или локаций).
this.make.text({
x: 400,
y: 500,
text: 'Long word incoming: Supercalifragilisticexpialidocious!',
origin: { x: 0.5, y: 0.5 },
style: {
font: 'bold 25px Arial',
fill: 'white',
wordWrap: { width: 300, useAdvancedWrap: true } // Длинное слово будет разбито
}
});
Что попробовать дальше
Phaser предоставляет два инструмента для переноса текста: простой (wordWrap: { width }) и продвинутый (wordWrap: { width, useAdvancedWrap: true }). Для большинства игровых интерфейсов, где текст генерируется динамически, рекомендуется сразу использовать расширенный режим — он обеспечивает чистый и предсказуемый результат. Поэкспериментируйте, применив перенос к тексту в диалоговых окнах, описаниях предметов или всплывающих подсказках. Попробуйте динамически менять свойство wordWrap.width в ответ на изменение размера игрового окна для создания адаптивных интерфейсов.
