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

В игровой механике часто требуется, чтобы объект плавно перемещался к указанной точке, например, для движения врага к игроку или перемещения снаряда. Реализация такого движения "вручную" через расчёты скорости может быть утомительной. Phaser с его модулем Arcade Physics предоставляет для этого элегантное решение — метод `physics.moveToObject`. В этой статье мы разберём, как заставить спрайт двигаться к цели за заданное время, используя этот удобный API.

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

    create ()
    {
        const flower = this.physics.add.image(100, 300, 'flower')
            .setBounce(1, 1)
            .setCollideWorldBounds(true);

        const cursor = this.add.image(0, 0, 'cursor').setVisible(false);

        this.add.text(10, 10, 'Click to set target', { fill: '#00ff00' });

        this.input.on('pointerdown', (pointer) =>
        {
            cursor.copyPosition(pointer).setVisible(true);

            // Move toward target in 1 second:
            this.physics.moveToObject(flower, cursor, 0, 1000);

            console.log('New speed is %.3f px/s', flower.body.velocity.length());

            // See <move and stop at position.js> for stopping.
        });
    }
}

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 загружаются необходимые изображения: спрайт цветка, который будет двигаться, и изображение курсора для визуализации цели.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('flower', 'assets/sprites/flower-exo.png');
    this.load.image('cursor', 'assets/sprites/drawcursor.png');
}

В методе create создаётся физический спрайт flower. Для него устанавливаются свойства: setBounce(1, 1) — упругость при столкновении (отскок по осям X и Y) и setCollideWorldBounds(true) — включение столкновений с границами мира. Также создаётся невидимый спрайт cursor, который будет отмечать цель.

const flower = this.physics.add.image(100, 300, 'flower')
    .setBounce(1, 1)
    .setCollideWorldBounds(true);

const cursor = this.add.image(0, 0, 'cursor').setVisible(false);

Обработка клика и запуск движения

На сцену выводится текстовая подсказка. Основная логика заключена в обработчике события pointerdown. При клике мышью позиция курсора (cursor) обновляется на позицию указателя и становится видимой.

this.add.text(10, 10, 'Click to set target', { fill: '#00ff00' });

this.input.on('pointerdown', (pointer) =>
{
    cursor.copyPosition(pointer).setVisible(true);

Затем вызывается ключевой метод this.physics.moveToObject(flower, cursor, 0, 1000). Он автоматически рассчитывает и устанавливает вектор скорости (body.velocity) для спрайта flower, чтобы тот достиг цели (cursor) за указанную длительность — 1000 миллисекунд (1 секунда). Третий параметр (скорость) в данном случае игнорируется, так как задана длительность.

this.physics.moveToObject(flower, cursor, 0, 1000);

Важные нюансы метода moveToObject

Метод physics.moveToObject упрощает управление движением. После его вывода в лог выводится новая величина скорости спрайта в пикселях в секунду, рассчитанная из установленного вектора скорости.

console.log('New speed is %.3f px/s', flower.body.velocity.length());

Важно понимать: объект продолжит движение с рассчитанной скоростью, даже если цель (cursor) после этого переместится. Для остановки в нужной точке требуется дополнительная логика (например, проверка расстояния). Авторы примера отсылают к другому примеру move and stop at position.js. Также обратите внимание, что в конфигурации физики включён debug: true, что позволяет видеть хитбоксы и векторы скорости на сцене.

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

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

Метод physics.moveToObject — это мощный инструмент для быстрой реализации движения к цели по времени или с заданной скоростью. Для экспериментов попробуйте изменить длительность движения, добавьте условие остановки при достижении определённого расстояния до цели или используйте этот метод для создания группы врагов, преследующих игрока.