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

В разработке игр часто требуется, чтобы физическая граница объекта отличалась от его визуального представления. Например, для создания более лёгкого геймплея или реализации «ауры» вокруг персонажа. Встроенная физика Arcade в Phaser 3 позволяет легко управлять размерами и положением коллайдера любого спрайта. В этой статье мы разберём пример, где физический контур спрайта Atari значительно превышает его графику. Этот приём полезен для создания больших, но визуально компактных препятствий, зон активации или упрощённых хитбоксов.

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

    create ()
    {
        const atari = this.physics.add.image(200, 400, 'atari').setImmovable(true);

        //  In this example the new collision box is much larger than the original sprite

        //  220x104 original size, 300x400 new size, the 'true' argument means "center it on the gameobject"
        atari.setSize(300, 260, true);

        //  And this sprite will collide with it
        const mushroom1 = this.physics.add.image(700, 350, 'mushroom');
        const mushroom2 = this.physics.add.image(200, 50, 'mushroom');

        mushroom1.setVelocity(-100, 0);
        mushroom2.setVelocity(0, 100);

        this.physics.add.collider(atari, [ mushroom1, mushroom2 ]);
    }
}

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

const game = new Phaser.Game(config);

Загрузка ресурсов и базовая настройка

В методе preload загружаются два изображения, которые будут использоваться как спрайты. Обратите внимание на использование setBaseURL — это удобно для указания корневого пути к ресурсам.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('atari', 'assets/sprites/atari130xe.png');
    this.load.image('mushroom', 'assets/sprites/mushroom2.png');
}

Создание статичного объекта с изменённым коллайдером

В методе create создаётся физический спрайт 'atari' и сразу же делается неподвижным с помощью setImmovable(true). Это ключевой момент: объект не будет реагировать на силы столкновения, оставаясь на месте.

Затем вызывается метод setSize. Его параметры: 1. Новая ширина коллайдера (300 пикселей). 2. Новая высота коллайдера (260 пикселей). 3. Флаг true — центрировать новый коллайдер относительно исходной позиции спрайта. Исходный спрайт имеет размер 220x104, поэтому новый коллайдер будет значительно больше и выйдет за границы видимой текстуры.

const atari = this.physics.add.image(200, 400, 'atari').setImmovable(true);
atari.setSize(300, 260, true);

Создание динамических объектов и настройка столкновений

Далее создаются два подвижных спрайта 'mushroom'. Им задаётся начальная скорость с помощью setVelocity, чтобы они двигались навстречу изменённому коллайдеру объекта 'atari'.

Финальный и важный шаг — регистрация столкновения между объектами. Метод this.physics.add.collider принимает первый аргумент (объект 'atari') и второй — массив из двух грибов. Phaser автоматически рассчитает столкновение между статичным объектом с большим коллайдером и каждым из движущихся спрайтов.

const mushroom1 = this.physics.add.image(700, 350, 'mushroom');
const mushroom2 = this.physics.add.image(200, 50, 'mushroom');

mushroom1.setVelocity(-100, 0);
mushroom2.setVelocity(0, 100);

this.physics.add.collider(atari, [ mushroom1, mushroom2 ]);

Конфигурация игры и включение отладки

Чтобы визуально наблюдать за изменёнными границами коллайдера, в конфигурации физического движка Arcade необходимо включить отладку: debug: true. При этом на сцене будут отрисованы контуры всех физических тел, что невероятно полезно при разработке и отладке механик.

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    parent: 'phaser-example',
    physics: {
        default: 'arcade',
        arcade: {
            debug: true // Включает отладочную графику для коллайдеров
        }
    },
    scene: Example
};

const game = new Phaser.Game(config);

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

Метод setSize — это мощный инструмент для тонкой настройки физики в Phaser 3, позволяющий отделить логику взаимодействия объектов от их визуального вида. Для экспериментов попробуйте: 1. Изменить флаг центрирования на false и посмотреть, как сместится коллайдер. 2. Сделать коллайдер меньше спрайта для создания «уязвимого ядра» у большого врага. 3. Использовать setOffset вместе с setSize для ещё более точного позиционирования области столкновения.