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

Детектирование конкретной отпущенной кнопки мыши — частый запрос в играх, будь то выпуск снаряда при отпускании ЛКМ или отмена действия через ПКМ. Часто разработчики проверяют только факт клика, но не то, какая именно кнопка была отпущена. Встроенные методы Phaser `pointer.leftButtonReleased()` и подобные позволяют легко и точно обрабатывать такие события. Эта статья покажет, как отслеживать отпускание любой кнопки мыши — от основной до дополнительных (вперёд/назад) — и использовать это для игровой механики.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    text2;
    text1;

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('logo', 'assets/sprites/phaser.png');
        this.load.image('asuna', 'assets/sprites/asuna_by_vali233.png');
        this.load.image('disk', 'assets/sprites/oz_pov_melting_disk.png');
        this.load.image('tree', 'assets/sprites/palm-tree-left.png');
    }

    create ()
    {
        this.text1 = this.add.text(10, 10, '', { fill: '#00ff00' });
        this.text2 = this.add.text(500, 10, '', { fill: '#00ff00' });

        this.input.mouse.disableContextMenu();

        this.input.on('pointerup', pointer =>
        {

            if (pointer.leftButtonReleased())
            {
                this.text2.setText('Left Button was released');
            }
            else if (pointer.rightButtonReleased())
            {
                this.text2.setText('Right Button was released');
            }
            else if (pointer.middleButtonReleased())
            {
                this.text2.setText('Middle Button was released');
            }
            else if (pointer.backButtonReleased())
            {
                this.text2.setText('Back Button was released');
            }
            else if (pointer.forwardButtonReleased())
            {
                this.text2.setText('Forward Button was released');
            }

        });
    }

    update ()
    {
        const pointer = this.input.activePointer;

        this.text1.setText([
            `x: ${pointer.worldX}`,
            `y: ${pointer.worldY}`,
            `isDown: ${pointer.isDown}`
        ]);
    }
}

const config = {
    width: 800,
    height: 600,
    type: Phaser.AUTO,
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

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

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

this.input.mouse.disableContextMenu();

Слушатель события pointerup

Основная логика обработки размещается в обработчике события 'pointerup'. Это событие срабатывает, когда любая кнопка указателя (мыши или касания) отпускается. Внутри обработчика мы получаем объект pointer, который содержит информацию о событии.

this.input.on('pointerup', pointer => {
    // Логика проверки кнопок здесь
});

Определение отпущенной кнопки

Объект pointer предоставляет набор булевых методов для точного определения, какая кнопка была отпущена именно в этом событии. Их следует вызывать только внутри обработчика 'pointerup'.

if (pointer.leftButtonReleased())
{
    this.text2.setText('Left Button was released');
}
else if (pointer.rightButtonReleased())
{
    this.text2.setText('Right Button was released');
}
else if (pointer.middleButtonReleased())
{
    this.text2.setText('Middle Button was released');
}
else if (pointer.backButtonReleased())
{
    this.text2.setText('Back Button was released');
}
else if (pointer.forwardButtonReleased())
{
    this.text2.setText('Forward Button was released');
}

Каждый метод (например, leftButtonReleased()) возвращает true только если соответствующая кнопка была отпущена в момент этого конкретного события pointerup. Это позволяет различать действия для разных кнопок.

Отслеживание состояния указателя в реальном времени

Помимо обработки событий, полезно в реальном времени отслеживать общее состояние указателя — его координаты и нажата ли какая-либо кнопка. Для этого используется метод update и свойство this.input.activePointer.

update ()
{
    const pointer = this.input.activePointer;

    this.text1.setText([
        `x: ${pointer.worldX}`,
        `y: ${pointer.worldY}`,
        `isDown: ${pointer.isDown}`
    ]);
}

pointer.worldX и pointer.worldY дают координаты в игровом мире, а pointer.isDown показывает, нажата ли в данный момент любая кнопка.

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

Использование методов pointer.leftButtonReleased() и их аналогов — самый чистый и надёжный способ обработки отпускания конкретных кнопок мыши в Phaser. Это открывает путь к созданию сложных механик ввода. Попробуйте реализовать зарядку выстрела: сила выстрела увеличивается, пока зажата ЛКМ, и рассчитывается в момент её отпускания. Или создайте контекстное меню игры, которое появляется при отпускании ПКМ, — теперь у вас есть точный инструмент для этого.