Отсечение объектов по камере

В Phaser камера (Camera) является инструментом, позволяющим управлять отображением сцены на экране. Она не изменяет позиции объектов в мире, а лишь определяет, какая часть сцены видна игроку. Основные параметры камеры включают положение (scrollX, scrollY), масштаб (zoom) и область видимости (viewport).

const camera = this.cameras.main;
camera.setBounds(0, 0, worldWidth, worldHeight);
camera.setZoom(1.5);

setBounds задаёт границы движения камеры в пределах игрового мира. Камера не может выйти за эти пределы, что важно для правильного отсечения объектов за пределами видимой области.

Понятие отсечения объектов

Отсечение объектов (culling) — процесс исключения из рендеринга тех объектов, которые находятся вне области видимости камеры. Это критически важно для производительности, особенно при большом количестве спрайтов или сложных сцен.

Phaser выполняет базовое отсечение автоматически для большинства объектов, таких как Sprite, Image, TilemapLayer. Объекты, чьи координаты полностью выходят за границы камеры, не отрисовываются, что снижает нагрузку на GPU.

sprite.setCull(true);

Для кастомных объектов можно использовать методы проверки попадания в область камеры. Например:

function isInCameraView(camera, gameObject) {
    const bounds = camera.worldView;
    return Phaser.Geom.Intersects.RectangleToRectangle(gameObject.getBounds(), bounds);
}

Здесь camera.worldView — прямоугольник, соответствующий текущей области видимости камеры в мировых координатах. Метод getBounds() возвращает границы объекта. Проверка пересечения позволяет определить, следует ли объект рендерить.

Оптимизация рендеринга через отсечение

  1. Использование Camera.cull для слоёв Tilemap Tilemap может содержать тысячи тайлов. Phaser автоматически выполняет отсечение видимых тайлов на каждом кадре, но при необходимости можно управлять этим вручную.
tilemapLayer.cull = true;
  1. Группы объектов (Group и Container) Отсечение работает и для групп, если включено свойство scrollFactor и объекты находятся в пределах камеры. Для кастомного поведения можно перебрать элементы группы:
group.getChildren().forEach(obj => {
    obj.visible = isInCameraView(this.cameras.main, obj);
});
  1. Кастомные объекты и эффекты Для объектов, не являющихся спрайтами или тайлами (например, сложные графические линии, эффекты частиц), необходимо вручную проверять их видимость. В противном случае они будут рендериться каждый кадр, снижая производительность.
graphics.clear();
group.getChildren().forEach(obj => {
    if (isInCameraView(this.cameras.main, obj)) {
        graphics.fillStyle(obj.color, 1);
        graphics.fillRect(obj.x, obj.y, obj.width, obj.height);
    }
});

Множественные камеры и отсечение

Phaser поддерживает несколько камер на одной сцене. Каждая камера имеет свой worldView, поэтому отсечение объектов выполняется индивидуально для каждой камеры. При этом важно учитывать:

  • Наложение камер (cameras.add) — объекты могут быть видимы только в одной из камер.
  • Параллакс (scrollFactor) — объекты с отличным от 1 значением могут пересекать границы камеры иначе, что требует корректного расчёта отсечения.
const cam1 = this.cameras.main;
const cam2 = this.cameras.add(0, 0, 400, 300);
cam2.setScroll(100, 50);

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

  • Использовать автоматическое отсечение Phaser для спрайтов и тайлов, чтобы минимизировать ручное управление.
  • Для динамических и кастомных объектов всегда проверять попадание в worldView.
  • При работе с группами или контейнерами использовать фильтрацию видимых объектов вместо полного рендеринга.
  • Множественные камеры требуют отдельной логики для каждого worldView, особенно если используются нестандартные масштабы или эффекты параллакса.

Эффективное отсечение объектов значительно снижает нагрузку на рендеринг, что особенно важно для мобильных устройств и сцен с большим количеством элементов. Правильное использование методов camera.worldView и проверки пересечения объектов с областью видимости позволяет создавать плавные и производительные игры в Phaser.