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

При создании игр часто возникает необходимость в более точных коллизиях, чем границы спрайта. Например, персонаж с широкой анимацией или объект с "мертвыми зонами". Phaser 3 Arcade Physics позволяет легко задавать пользовательские прямоугольники столкновений (bounding box), которые могут быть меньше или больше визуального спрайта. В этой статье разберем, как использовать метод `setSize()` для создания точных физических взаимодействий.

Версия 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 smaller than the original sprite

        //  220x104 original size, 110x52 new size, the 'true' argument means "center it on the gameobject"
        atari.setSize(110, 52, 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);

Зачем менять размер коллайдера?

По умолчанию физическое тело (body) в Arcade Physics создается по размеру текстуры спрайта. Это не всегда соответствует игровому замыслу. Визуальные "крылья" самолета, аура вокруг магического шара или просто желание сделать столкновения более "человечными" для персонажа — все это требует настройки хитбокса.

Метод setSize() класса Arcade Physics Body позволяет переопределить размер и положение прямоугольника столкновений, не затрагивая отрисовку спрайта. В примере мы уменьшаем хитбокс компьютера Atari, чтобы грибы сталкивались именно с его корпусом, а не с краями спрайта.

Разбор кода: создание сцены и спрайтов

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

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

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

Грибам задается начальная скорость с помощью setVelocity. Столкновение между Atari и массивом грибов регистрируется через this.physics.add.collider.

Волшебный метод `setSize()`

Вот где происходит магия. Исходный спрайт atari имеет размер 220x104 пикселя. Мы задаем новый размер коллайдера — 110x52.

atari.setSize(110, 52, true);

Третий аргумент (center) — булево значение. Если true, новый прямоугольник столкновений будет отцентрирован относительно исходной позиции тела. Если false, его верхний левый угол совпадет с верхним левым углом исходного тела. В нашем случае центрирование позволяет уменьшить хитбокс равномерно со всех сторон.

**Важно:** setSize() — это метод тела (Body), но он вызывается от спрайта, так как в Arcade Physics спрайт является прокси для своего физического тела.

Визуализация и отладка

Чтобы увидеть, что именно происходит, в конфигурации физики включен режим отладки:

physics: {
    default: 'arcade',
    arcade: {
        debug: true
    }
}

При debug: true поверх спрайтов отрисовываются контуры их физических тел. Вы увидите, что зеленый контур (коллайдер) у atari теперь в два раза меньше красного контура спрайта. Это незаменимый инструмент для тонкой настройки столкновений.

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

1. **Смещение (setOffset):** Вместе с setSize() часто используют body.setOffset(x, y) для смещения коллайдера относительно спрайта. Например, для создания хитбокса только для верхней части объекта. 2. **Круглые коллайдеры:** Для более органичных столкновений используйте setCircle(radius) или setCircle(radius, offsetX, offsetY), чтобы задать тело в форме круга. 3. **Производительность:** Работа с прямоугольными (setSize) и круглыми телами в Arcade Physics очень эффективна. Избегайте создания множества мелких тел для одного спрайта — один измененный коллайдер почти всегда лучше.

Помните, что setSize влияет только на обнаружение столкновений. Методы для получения границ спрайта, например getBounds, по-прежнему возвращают исходные размеры текстуры.

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

Использование setSize() — это простой и мощный способ сделать физику вашей игры точной и правдоподобной. Поэкспериментируйте: создайте персонажа, у которого коллайдер меньше роста (чтобы предметы падали "перед ним"), или платформу, хитбокс которой меньше визуала, чтобы создавать иллюзию возможности зацепиться за край. Сочетание setSize и setOffset откроет полный контроль над игровыми взаимодействиями.