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

Физические движки в играх часто ограничены стандартными силами, такими как гравитация или ветер, действующими одинаково на все объекты. Но что, если вам нужно, чтобы определённый объект, подобно чёрной дыре или магниту, притягивал к себе остальные? Встроенный в Phaser Matter.js плагин Attractor позволяет легко реализовать такие кастомные силы притяжения между любыми телами. Эта статья покажет, как настроить плагин и создать объект-«солнце», которое будет притягивать к себе «пришельцев», открывая путь для механик гравитационных пуль, магнитных ловушек или орбитального движения.

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


// const { Physics } = require("phaser");

class Example extends Phaser.Scene
{
    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('sun', 'assets/tests/space/sun.png');
        this.load.image('alien', 'assets/sprites/space-baddie.png');
    }

    create ()
    {
        //  You can enable the Attractors plugin either via the game config (see above), or explicitly in code:
        // this.matter.enableAttractorPlugin();

        this.matter.world.setBounds();

        this.aliens = this.matter.add.imageStack('alien', null, 0, 500, 50, 2, 0, 0, {
            mass: 1,
            ignorePointer: true
        });

        this.sun = this.matter.add.image(400, 200, 'sun', null, {
            shape: {
                type: 'circle',
                radius: 64
            },
            attractors: [
                (bodyA, bodyB) => ({
                    x: (bodyA.position.x - bodyB.position.x) * 0.000001,
                    y: (bodyA.position.y - bodyB.position.y) * 0.000001
                })
            ]
        });

        this.matter.add.mouseSpring();
    }

    update ()
    {
        const bodies = this.aliens.bodies;
        const force = { x: 0, y: -0.00001 };

        for (let i = 0; i < bodies.length; i++) 
        {
            // Phaser.Physics.Matter.Matter.Body.applyForce(bodies[i], bodies[i].position, force);
        }
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#000000',
    parent: 'phaser-example',
    physics: {
        default: 'matter',
        matter: {
            gravity: {
                scale: 0
            },
        }
    },
    scene: Example
};

const game = new Phaser.Game(config);

Подготовка сцены и загрузка ассетов

В начале, как и в любом проекте Phaser, мы загружаем необходимые изображения. В методе preload указывается базовый URL и загружаются два спрайта: «солнце» и «пришелец». Важно, что для корректной работы плагина Attractor используется физический движок Matter.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('sun', 'assets/tests/space/sun.png');
    this.load.image('alien', 'assets/sprites/space-baddie.png');
}

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

В методе create мы настраиваем мир. Строка this.matter.world.setBounds() создаёт границы по краям игрового поля. Далее создаётся группа тел — стопка спрайтов «пришельцев» с помощью this.matter.add.imageStack. Параметры задают текстуру, начальные координаты, количество спрайтов в рядах и столбцах, а также их физические свойства, такие как mass (масса).

create ()
{
    this.matter.world.setBounds();

    this.aliens = this.matter.add.imageStack('alien', null, 0, 500, 50, 2, 0, 0, {
        mass: 1,
        ignorePointer: true
    });

Затем создаётся ключевой объект — «солнце». Обратите внимание на опцию shape, которая определяет физическую форму тела (круг), и, самое главное, массив attractors.

this.sun = this.matter.add.image(400, 200, 'sun', null, {
        shape: {
            type: 'circle',
            radius: 64
        },
        attractors: [
            (bodyA, bodyB) => ({
                x: (bodyA.position.x - bodyB.position.x) * 0.000001,
                y: (bodyA.position.y - bodyB.position.y) * 0.000001
            })
        ]
    });

Как работает Attractor функция

Массив attractors содержит одну или несколько функций. Каждая функция автоматически вызывается движком Matter для расчёта силы притяжения между двумя телами: bodyA (тело, к которому привязан аттрактор — наше «солнце») и bodyB («пришелец» или любое другое тело в мире). Функция должна вернуть объект с вектором силы { x, y }, который будет применён к bodyB.

В нашем примере сила рассчитывается просто: разница координат по осям X и Y умножается на очень маленький коэффициент (0.000001). Эта формула создаёт силу, направленную от bodyB («пришельца») к bodyA («солнцу»), так как вектор строится как (positionA - positionB). Чем ближе тела, тем меньше разница координат и слабее сила, что имитирует классическое гравитационное притяжение.

Включение плагина и вспомогательные инструменты

Плагин Attractor может быть включён глобально в конфигурации игры (как показано в исходном коде примера через plugins), либо непосредственно в коде сцены с помощью this.matter.enableAttractorPlugin(). В данном примере он уже включён через конфиг.

Строка this.matter.add.mouseSpring() добавляет пружину, привязанную к курсору мыши, что позволяет вручную взаимодействовать с телами и наглядно видеть, как они притягиваются к «солнцу».

this.matter.add.mouseSpring();
}

Глобальная конфигурация игры

Ключевой момент для работы примера — правильная настройка физики Matter в конфиге игры. Обратите внимание: гравитация отключена (gravity: { scale: 0 }). Это важно, чтобы единственной силой, действующей на «пришельцев», было притяжение от «солнца». Если включить стандартную гравитацию, тела будут также падать вниз.

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#000000',
    parent: 'phaser-example',
    physics: {
        default: 'matter',
        matter: {
            gravity: {
                scale: 0
            },
            plugins: {
                attractors: true
            }
        }
    },
    scene: Example
};

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

Плагин Attractor в Phaser — это мощный и гибкий инструмент для создания нестандартных физических взаимодействий. Вы можете привязать функцию-аттрактор к любому телу, будь то планета, магнит или вакуумная воронка. Для экспериментов попробуйте: изменить формулу силы для создания отталкивания (repulsor), сделать силу зависимой от расстояния по квадратичному закону (реалистичная гравитация), добавить нескольким объектам разные аттракторы или динамически включать/отключать притяжение при определённых событиях в игре.