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

При создании игр с большим количеством статичных или редко меняющихся спрайтов (частицы, элементы фона, тайлы) классические `Sprite` объекты могут стать узким местом производительности. Каждый такой объект несет накладные расходы на управление физикой, анимацией и событиями. Пример 'Single Image Bob' демонстрирует альтернативный, высокопроизводительный подход с использованием `Blitter` и `Bob`. Это система отрисовки, которая работает с 'штампованными' изображениями (`Bob`) на канвасе, минимизируя вызовы отрисовки. Она идеальна для случаев, когда вам нужна максимальная скорость отрисовки множества копий одного изображения без лишних функциональных наворотов.

Версия 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('atari', 'assets/sprites/atari130xe.png');
    }

    create ()
    {
        const blitter = this.add.blitter(0, 0, 'atari');

        const bob = blitter.create(100, 100);

        console.log(blitter.children);
        console.log(blitter.getRenderList());
    }
}

const config = {
    type: Phaser.CANVAS,
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

Что такое Blitter и Bob?

Blitter — это специальный игровой объект (Phaser.GameObjects.Blitter), который служит контейнером и менеджером для объектов Bob. Его можно представить как доску для штамповки.

Bob (Phaser.GameObjects.Bob) — это легковесный объект, представляющий одну отрисовку (один «штамп») текстуры в определенной позиции на экране. Bob не является Sprite — у него нет тела для физики, компонентов для анимации или встроенных методов для обработки ввода. Это просто данные для отрисовки: позиция (x, y), кадр текстуры и флаги видимости.

Их основная сила — в объединенной пакетной отрисовке. Все Bob, принадлежащие одному Blitter, рисуются за один вызов отрисовщика (рендер-колл), что критически важно для производительности при работе с тысячами объектов.

Разбор примера: от загрузки до создания

Давайте пройдемся по коду примера шаг за шагом.

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

this.load.image('atari', 'assets/sprites/atari130xe.png');

В методе create происходит магия. Сначала создается сам объект Blitter. Его координаты (0, 0) задают начало системы координат для всех его дочерних Bob.

const blitter = this.add.blitter(0, 0, 'atari');

Затем с помощью метода blitter.create(x, y) создается один объект Bob. Аргументы `xиyзадают его позицию относительно родительскогоBlitter. В данном случае спрайтatari` появится на экране в координатах (100, 100).

const bob = blitter.create(100, 100);

Управление Bob и внутренняя структура Blitter

Созданный Bob автоматически добавляется во внутренние списки Blitter. Пример выводит в консоль два важных свойства, которые помогают понять внутреннее устройство.

blitter.children — это массив всех созданных объектов Bob. Вы можете перебирать его в цикле, чтобы массово изменять их свойства, например, позиции для создания волнового эффекта.

console.log(blitter.children);

blitter.getRenderList() — это оптимизированный массив Bob, которые *фактически* будут отрисованы в текущем кадре. Если Bob невидим (bob.visible = false), он будет исключен из этого списка, что еще больше ускоряет рендеринг.

console.log(blitter.getRenderList());

Каждый Bob имеет простейшие свойства для управления:

bob.x = 200; // Изменить позицию по X
bob.y = 150; // Изменить позицию по Y
bob.visible = false; // Скрыть этот Bob
bob.frame = frameObject; // Изменить отображаемый кадр текстуры (если используется атлас)

Ключевые отличия от обычных Sprite

1. **Производительность:** Один Blitter с тысячей Bob выполнит один вызов отрисовки. Тысяча отдельных Sprite — тысячу вызовов. 2. **Функциональность:** У Bob нет тела для this.physics.add.image, нет анимаций, нет обработчиков событий мыши/касания. Это «тупые» пиксели. 3. **Управление:** Bob управляются через родительский Blitter или напрямую через ссылку. Для их перемещения вы просто меняете свойства `xиy`, а движок сам позаботится об эффективной отрисовке. 4. **Память:** Bob использует меньше памяти, чем полноценный Sprite.

Используйте Blitter, когда вам нужно много статичных или простейших объектов (звездный фон, пыль, трава, пули в классическом шутере). Используйте Sprite, когда объекту нужна физика, сложная анимация или интерактивность.

Практические паттерны использования

**Создание частиц для взрыва:**

createExplosion(x, y) {
    const particles = this.add.blitter(x, y, 'particle');
    for (let i = 0; i < 50; i++) {
        const bob = particles.create(0, 0);
        bob.x = Phaser.Math.Between(-20, 20);
        bob.y = Phaser.Math.Between(-20, 20);
        // Установка таймера на скрытие Bob через 300мс
        this.time.delayedCall(300, () => { bob.visible = false; });
    }
}

**Массовое обновление (параллакс-фон):**

// В update()
this.blitterStars.children.forEach((bob, index) => {
    // Медленно двигаем каждый Bob влево с разной скоростью
    bob.x -= (index % 3 + 1) * 0.1;
    if (bob.x < -100) bob.x = 800; // Возвращаем на правый край экрана
});

**Использование атласов:** Вы можете создавать Bob с разными кадрами из одной текстуры, что полезно для тайловых карт или наборов иконок.

const blitter = this.add.blitter(0, 0, 'tileset');
const frame = this.textures.getFrame('tileset', 'grass');
const bob = blitter.create(64, 128);
// Устанавливаем конкретный кадр текстуры
bob.frame = frame;

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

Blitter — это мощный инструмент оптимизации для специфичных задач в Phaser. Он позволяет достичь высокой частоты кадров в сценах с огромным количеством визуальных объектов, жертвуя их функциональной сложностью. **Идеи для экспериментов:** 1. Создайте систему звездного поля с 5000 Bob, где каждая звезда движется с уникальной скоростью для эффекта параллакса. 2. Реализуйте простейшую систему частиц для выхлопа корабля, создавая и переиспользуя Bob из пула. 3. Сравните FPS в сцене с 2000 Bob и 2000 Sprite при их одновременном движении. 4. Используйте Blitter для отрисовки статичного тайлового фона большой карты, генерируя Bob только для видимой области.