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

В играх часто требуется реагировать, когда игрок или объект входит в определенную область. Например, для активации ловушки, триггера диалога или зоны повышенной гравитации. Phaser Physics позволяет легко создавать такие невидимые зоны и отслеживать пересечения с другими физическими телами. В этой статье мы разберем пример, где используется `Phaser.Physics.Arcade.StaticBody` для зоны и метод `overlap` для обнаружения в ней динамических тел. Вы научитесь создавать невидимые триггерные области и реагировать на события пересечения в реальном времени.

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

    create ()
    {
        const zone = this.add.zone(300, 200, 200, 200);

        // Static body
        this.physics.add.existing(zone, true);

        const blocks = this.physics.add.group({
            defaultKey: 'block',
            bounceX: 1,
            bounceY: 1,
            collideWorldBounds: true
        });

        blocks.create(100, 200).setVelocity(100, 200);
        blocks.create(500, 200).setVelocity(-100, -100);
        blocks.create(300, 400).setVelocity(60, 100);
        blocks.create(600, 300).setVelocity(-30, -50);

        this.physics.add.overlap(zone, blocks, (_zone, block) =>
        {
            block.setAlpha(0.5);
        });
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    parent: 'phaser-example',
    physics: {
        default: 'arcade',
        arcade: {
            debug: true,
            gravity: { y: 200 }
        }
    },
    scene: Example
};

const game = new Phaser.Game(config);


Создание зоны и превращение её в статическое тело

В Phaser Phaser.GameObjects.Zone — это невидимый прямоугольный объект, предназначенный для обработки событий и логики. Но чтобы использовать его в физических расчетах, например, для обнаружения столкновений или пересечений, ему необходимо добавить физическое тело.

const zone = this.add.zone(300, 200, 200, 200);
this.physics.add.existing(zone, true);

Первой строкой мы создаем зону с центром в точке (300, 200) и размерами 200x200 пикселей. Вторая строка — ключевая. Метод this.physics.add.existing() добавляет к уже существующему игровому объекту тело Arcade Physics. Второй аргумент true указывает, что тело должно быть **статическим** (static: true). Статическое тело не подвержено влиянию сил (гравитации, толчков) и не двигается при столкновениях, что идеально подходит для триггерной зоны.

Создание группы динамических тел

Для демонстрации работы зоны нам нужны движущиеся объекты, пересечение с которыми мы будем отслеживать. Удобнее всего создать для этого физическую группу.

const blocks = this.physics.add.group({
    defaultKey: 'block',
    bounceX: 1,
    bounceY: 1,
    collideWorldBounds: true
});

blocks.create(100, 200).setVelocity(100, 200);
blocks.create(500, 200).setVelocity(-100, -100);
// ... другие блоки

Здесь создается группа blocks. Параметр defaultKey указывает текстуру ('block'), которая будет использоваться для всех создаваемых в группе спрайтов. bounceX и bounceY задают коэффициент упругости (1 — идеальный отскок). collideWorldBounds включает столкновение с границами мира.

Метод blocks.create() создает в группе отдельный спрайт с физическим телом в указанных координатах. Метод setVelocity() сразу задает ему начальную скорость, заставляя двигаться.

Отслеживание пересечений с помощью метода overlap

Ядро логики примера — метод this.physics.add.overlap(), который проверяет пересечение двух объектов или групп и запускает callback-функцию при каждом обнаруженном факте пересечения.

this.physics.add.overlap(zone, blocks, (_zone, block) =>
{
    block.setAlpha(0.5);
});

Первые два аргумента — это объекты для проверки: наша зона (zone) и группа блоков (blocks). Phaser будет автоматически проверять пересечение зоны с каждым телом из группы.

Третий аргумент — функция-обработчик. Она вызывается **каждый раз**, когда происходит пересечение. В параметры _zone и block автоматически передаются конкретные объекты, которые пересеклись (в нашем случае это всегда наша зона и один из блоков). Внутри обработчика мы изменяем прозрачность блока, попавшего в зону, с помощью block.setAlpha(0.5).

Важные детали работы overlap и отладка

Важно понимать, что overlap — это **процесс**, а не событие. Проверка происходит на каждом игровом кадре, и callback будет вызываться постоянно, пока объекты пересекаются.

physics: {
    default: 'arcade',
    arcade: {
        debug: true,
        gravity: { y: 200 }
    }
}

Конфигурация физики в этом примере включает два важных момента. Во-первых, gravity: { y: 200 } добавляет постоянное ускорение вниз, заставляя блоки падать и отскакивать, что создает динамичную картину пересечений. Во-вторых, debug: true включает отладочную отрисовку. Вы увидите, что зона обведена зеленой рамкой (признак статического тела), а у блоков будут видны их физические границы (тела). Это невероятно полезно для визуальной настройки.

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

Комбинация Zone, StaticBody и overlap предоставляет мощный и производительный инструмент для создания триггерных областей в вашей игре. Вы можете реагировать на вход и выход объекта, менять его состояние или активировать игровые события. **Идеи для экспериментов:** 1. Измените логику в callback-функции, чтобы блок становился полупрозрачным только при **первом** входе в зону, а при выходе возвращал прозрачность. Для этого вам понадобится отслеживать состояние каждого блока. 2. Сделайте зону не статической, а динамической телом (this.physics.add.existing(zone, false)) и посмотрите, как она будет реагировать на столкновения с блоками. 3. Используйте collider вместо overlap, чтобы блоки не могли проходить сквозь зону, а отталкивались от её границ.