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

В игровой механике часто требуется менять свойства объектов в реальном времени — например, увеличивать врага после получения урона или растить собираемый предмет. В примере показано, как изменять масштаб физического тела в движке Matter.js с сохранением корректных коллизий. Этот подход полезен для создания интерактивных объектов, реагирующих на действия игрока, без необходимости пересоздавать тело и терять его физическое состояние.

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

    create ()
    {
        this.scale = 1.1;
        this.matter.world.setBounds().disableGravity();

        //  By default it will create a rectangular body the size of the texture
        const rect = this.matter.add.image(200, 50, 'blue');

        //  Just make the body move around and bounce
        rect.setVelocity(3, 1);
        rect.setAngularVelocity(0.01);
        rect.setBounce(1);
        rect.setFriction(0, 0, 0);

        rect.setInteractive();

        rect.on('pointerup', () =>
        {

            rect.setScale(this.scale);

            this.scale += 0.1;

            rect.setVelocity(Phaser.Math.Between(-4, 4), Phaser.Math.Between(-2, 2));

        });
    }
}

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

const game = new Phaser.Game(config);

Настройка физики и создание тела

В примере используется физический плагин Matter.js, который настраивается в конфигурации игры. Ключевой параметр debug: true включает визуализацию тел для отладки.

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

В методе create сцена инициализирует мир: границы устанавливаются методом setBounds, а гравитация отключается. Объект создаётся через this.matter.add.image, который автоматически генерирует прямоугольное тело по размеру текстуры 'blue'.

this.matter.world.setBounds().disableGravity();
const rect = this.matter.add.image(200, 50, 'blue');

Задание движения и интерактивности

Созданному телу сразу задаётся движение. Метод setVelocity устанавливает линейную скорость, а setAngularVelocity — вращательную. Параметры setBounce и setFriction настраивают упругость и трение: здесь отскок максимальный (`1), а трение отсутствует (0`).

rect.setVelocity(3, 1);
rect.setAngularVelocity(0.01);
rect.setBounce(1);
rect.setFriction(0, 0, 0);

Чтобы объект реагировал на клики, он делается интерактивным через setInteractive. Это стандартный подход Phaser для обработки указателя.

rect.setInteractive();

Обработка клика и изменение масштаба

При клике на объект срабатывает событие pointerup. В обработчике сначала меняется масштаб тела через setScale, используя переменную this.scale. Затем эта переменная увеличивается для следующего клика.

rect.on('pointerup', () => {
    rect.setScale(this.scale);
    this.scale += 0.1;
});

Важно: Matter.js автоматически обновляет границы коллизий тела при изменении масштаба. Это позволяет сохранять физические взаимодействия без ручного перерасчёта. После масштабирования телу задаётся новая случайная скорость через Phaser.Math.Between.

rect.setVelocity(Phaser.Math.Between(-4, 4), Phaser.Math.Between(-2, 2));

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

Изменение масштаба физического тела через setScale в Matter.js — простой способ динамически менять размеры объекта с сохранением коллизий. Для экспериментов попробуйте: анимировать масштабирование через tweens, применять его к составным телам, менять не только размер, но и плотность тела методом setDensity или создавать цепную реакцию при клике на несколько связанных объектов.