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

Работа с текстом в играх часто требует хирургической точности. Неправильно установленная точка привязки может испортить выравнивание интерфейса, сделать надписи на кнопках кривыми или сместить координаты HUD. Этот пример наглядно демонстрирует, как метод `setOrigin()` контролирует точку отсчёта для bitmap-шрифтов. Вы научитесь позиционировать текст относительно его границ, что является ключом к созданию аккуратного и отзывчивого игрового интерфейса.

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

Живой запуск

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

Исходный код


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

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.bitmapFont('gothic', 'assets/fonts/bitmap/gothic.png', 'assets/fonts/bitmap/gothic.xml');
        this.load.bitmapFont('hyper', 'assets/fonts/bitmap/hyperdrive.png', 'assets/fonts/bitmap/hyperdrive.xml');
    }

    create ()
    {
        const graphics = this.add.graphics({ x: 0, y: 0, fillStyle: { color: 0xff00ff, alpha: 0.6 }, lineStyle: { color: 0x00ff00 } });

        const text1 = this.add.bitmapText(400, 0, 'gothic', 'Phaser 3', 70).setOrigin(0);
        const text2 = this.add.bitmapText(400, 200, 'gothic', 'Phaser 3', 70).setOrigin(0.5);
        const text3 = this.add.bitmapText(400, 400, 'gothic', 'Phaser 3', 70).setOrigin(1);

        const bounds1 = text1.getTextBounds();
        const bounds2 = text2.getTextBounds();
        const bounds3 = text3.getTextBounds();

        graphics.lineBetween(400, 0, 400, 600);

        graphics.fillRect(bounds1.global.x, bounds1.global.y, bounds1.global.width, bounds1.global.height);
        graphics.fillRect(bounds2.global.x, bounds2.global.y, bounds2.global.width, bounds2.global.height);
        graphics.fillRect(bounds3.global.x, bounds3.global.y, bounds3.global.width, bounds3.global.height);
    }
}

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

const game = new Phaser.Game(config);

Загрузка bitmap-шрифтов

Перед использованием bitmap-шрифт необходимо загрузить в кеш игры. В отличие от системных шрифтов, bitmap-шрифт — это пара файлов: изображение (PNG) со всеми символами и файл данных (XML или JSON), описывающий положение каждого глифа.

Метод this.load.bitmapFont() принимает три аргумента: ключ для последующего обращения, путь к изображению и путь к файлу с метаданными.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.bitmapFont('gothic', 'assets/fonts/bitmap/gothic.png', 'assets/fonts/bitmap/gothic.xml');
    this.load.bitmapFont('hyper', 'assets/fonts/bitmap/hyperdrive.png', 'assets/fonts/bitmap/hyperdrive.xml');
}

В этом примере загружаются два шрифта: 'gothic' и 'hyper'. Для демонстрации используется только первый. setBaseURL() задаёт базовый URL, чтобы не указывать полный путь для каждого ресурса.

Создание текста и установка точки отсчёта

Bitmap-текст создаётся методом this.add.bitmapText(). Важно понимать, что первые два аргумента (x, y) задают позицию не условного «левого верхнего угла» текста, а именно его точки отсчёта (origin).

Метод setOrigin() принимает значения от 0 до 1 по осям X и Y. Значение 0 привязывает позицию к левому/верхнему краю, 0.5 — к центру, а 1 — к правому/нижнему краю текстового блока.

const text1 = this.add.bitmapText(400, 0, 'gothic', 'Phaser 3', 70).setOrigin(0);
const text2 = this.add.bitmapText(400, 200, 'gothic', 'Phaser 3', 70).setOrigin(0.5);
const text3 = this.add.bitmapText(400, 400, 'gothic', 'Phaser 3', 70).setOrigin(1);

Все три текстовых объекта созданы на одной вертикальной линии X=400, но визуально они выровнены по-разному относительно этой линии, потому что их точка отсчёта изменена. text1 (origin 0) начинается от линии, text2 (origin 0.5) центрирован на ней, а text3 (origin 1) заканчивается на ней.

Визуализация границ и позиции

Чтобы понять, где на самом деле находятся границы текстового объекта, пример использует графический слой (Graphics). Ключевую роль играет метод getTextBounds(), который возвращает объект с глобальными координатами и размерами области, занимаемой текстом.

const bounds1 = text1.getTextBounds();
const bounds2 = text2.getTextBounds();
const bounds3 = text3.getTextBounds();

Полученные границы используются для отрисовки полупрозрачных прямоугольников вокруг каждого текстового блока. Это наглядно показывает, как меняется положение одной и той же текстовой строки относительно опорной точки (вертикальной зелёной линии).

const graphics = this.add.graphics({ x: 0, y: 0, fillStyle: { color: 0xff00ff, alpha: 0.6 }, lineStyle: { color: 0x00ff00 } });

graphics.lineBetween(400, 0, 400, 600);

graphics.fillRect(bounds1.global.x, bounds1.global.y, bounds1.global.width, bounds1.global.height);
graphics.fillRect(bounds2.global.x, bounds2.global.y, bounds2.global.width, bounds2.global.height);
graphics.fillRect(bounds3.global.x, bounds3.global.y, bounds3.global.width, bounds3.global.height);

Практическое применение

Понимание setOrigin() критически важно для: 1. **Выравнивания интерфейса:** Чтобы текст на кнопке был строго по центру, используйте setOrigin(0.5). 2. **Создания HUD:** Показатели здоровья или очков, которые должны быть прижаты к краю экрана, удобно позиционировать с setOrigin(1) для выравнивания по правому краю. 3. **Анимации текста:** Если вы хотите вращать текст вокруг его центра, origin должен быть (0.5, 0.5). Вращение текста с origin (0, 0) будет происходить вокруг его левого верхнего угла, что выглядит неестественно.

// Текст по центру кнопки
const buttonText = this.add.bitmapText(buttonCenterX, buttonCenterY, 'font', 'Играть', 32).setOrigin(0.5);

// Счёт, прижатый к правому верхнему углу экрана
const scoreText = this.add.bitmapText(780, 20, 'font', 'Score: 0', 24).setOrigin(1, 0);

Метод setOrigin() можно вызывать не только с одним значением для обеих осей, но и с двумя: setOrigin(1, 0) установит точку отсчёта в правый верхний угол.

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

Метод setOrigin() — это простой, но мощный инструмент для точного контроля над положением bitmap-текста. Он превращает позицию (x, y) из абстрактных координат в осмысленную точку привязки, будь то левый угол, центр или правый край текстового блока. **Идеи для экспериментов:** 1. Попробуйте анимировать текст с разными значениями origin, используя tweens для вращения или масштабирования, и наблюдайте за разницей. 2. Создайте панель статистики, где разные текстовые поля (имя, значение) выровнены по левому и правому краю относительно одной линии. 3. Используйте getTextBounds() динамически, чтобы другие игровые объекты (например, подчёркивание) могли точно следовать за изменяющимся по длине текстом.