О чем этот пример
Перетаскивание объектов — базовый механизм взаимодействия в играх. Часто требуется ограничить движение спрайта, например, только по оси X, чтобы создать эффект слайдера, ползунка или перемещения платформы по рельсам. В этой статье мы разберем, как реализовать такое ограничение, используя событие `drag` и математические функции Phaser. Этот подход полезен для создания интуитивных интерфейсов, головоломок или игровых механик, где свобода перемещения объекта должна быть контролируемой. Мы не будем подключать физику, а сосредоточимся на простом и эффективном Input Manager.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
constructor()
{
super();
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/skies/gradient8.png');
this.load.atlas('blocks', 'assets/sprites/blocks.png', 'assets/sprites/blocks.json');
}
create ()
{
this.add.image(400, 300, 'bg');
this.add.text(16, 16, 'Drag the Sprites horizontally').setFontSize(24).setShadow(1, 1);
const block1 = this.add.sprite(400, 150, 'blocks', 'metal');
const block2 = this.add.sprite(400, 300, 'blocks', 'platform');
const block3 = this.add.sprite(400, 450, 'blocks', 'wooden');
block1.setInteractive({ draggable: true });
block2.setInteractive({ draggable: true });
block3.setInteractive({ draggable: true });
this.input.on('drag', (pointer, gameObject, dragX) => {
// By clamping dragX we can keep it within
// whatever bounds we need
dragX = Phaser.Math.Clamp(dragX, 100, 700);
// By only applying the dragX we can limit the drag
// to be horizontal only
gameObject.x = dragX;
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и спрайтов
В методе preload загружаются необходимые ресурсы: фон и атлас спрайтов. Атлас blocks содержит несколько изображений, что позволяет создавать спрайты из разных фреймов.
В create мы добавляем фон, текстовую подсказку и три спрайта. Каждый спрайт создается с указанием текстуры (blocks) и конкретного фрейма из атласа (metal, platform, wooden).
const block1 = this.add.sprite(400, 150, 'blocks', 'metal');
const block2 = this.add.sprite(400, 300, 'blocks', 'platform');
const block3 = this.add.sprite(400, 450, 'blocks', 'wooden');
Ключевой шаг — сделать каждый спрайт интерактивным с опцией draggable: true. Это регистрирует объект в системе ввода Phaser для обработки событий перетаскивания.
block1.setInteractive({ draggable: true });
block2.setInteractive({ draggable: true });
block3.setInteractive({ draggable: true });
Обработка события drag
Сердце механизма — обработчик события drag, который срабатывает при каждом перемещении мыши или касании во время перетаскивания.
this.input.on('drag', (pointer, gameObject, dragX) => {
// Код обработки
});
Обратный вызов получает три параметра:
- pointer: информация об устройстве ввода (мышь, касание).
- gameObject: ссылка на перетаскиваемый спрайт (в нашем случае block1, block2 или block3).
- dragX: вычисленная координата X, куда система ввода предлагает переместить объект.
Важно понимать, что система ввода сама по себе не меняет позицию объекта. Это ответственность разработчика внутри обработчика. По умолчанию, если не назначить обработчик, объект будет свободно следовать за курсором.
Ограничение движения и применение координат
Внутри обработчика мы выполняем две важные операции.
Во-первых, ограничиваем значение dragX с помощью Phaser.Math.Clamp. Эта функция гарантирует, что координата останется в заданном диапазоне.
dragX = Phaser.Math.Clamp(dragX, 100, 700);
Здесь dragX не выйдет за пределы от 100 до 700 пикселей по горизонтали. Это создает невидимые границы для перетаскивания.
Во-вторых, мы присваиваем зажатое значение dragX свойству gameObject.x. Обратите внимание, что мы игнорируем координату Y (dragY), которая также передается в полной сигнатуре события. Именно это и обеспечивает горизонтальное ограничение — вертикальная позиция объекта остается неизменной.
gameObject.x = dragX;
Таким образом, объект может двигаться только по оси X в пределах от 100 до 700.
Конфигурация игры
Код завершается стандартной конфигурацией игры Phaser. Указывается тип рендерера (AUTO), размеры холста и связь с HTML-элементом (parent).
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Эта конфигурация создает игровой экземпляр размером 800x600 пикселей, который будет отрисован внутри элемента с id='phaser-example'. Сцена Example, которую мы описали, будет запущена автоматически.
Что попробовать дальше
Вы научились ограничивать перетаскивание объектов по горизонтали с помощью события drag и функции Phaser.Math.Clamp. Это простая, но мощная техника для создания управляемых интерактивных элементов.
Для экспериментов попробуйте:
1. Изменить диапазон в Clamp, чтобы объекты двигались в другой области экрана.
2. Реализовать вертикальное или диагональное ограничение, манипулируя свойством gameObject.y.
3. Добавить «щелчок» или фиксацию к определенным позициям (сетке) внутри обработчика dragend.
4. Привязать эту логику к UI-элементам, например, для создания ползунков громкости или настроек.
