Объединение ввода в единый контроллер

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

Концепция универсального контроллера

Объединение ввода в единый контроллер позволяет создать абстракцию, которая скрывает сложности взаимодействия с различными типами ввода. Такой подход имеет несколько преимуществ:

  • Унифицированный интерфейс: программист может работать с единым API, не беспокоясь о различиях между устройствами.
  • Гибкость: можно легко добавить поддержку новых типов ввода без значительных изменений в коде.
  • Масштабируемость: по мере расширения приложения или игры добавление новых источников ввода не приведет к необходимости переписывать основную логику.

Использование библиотеки pc.Input

В PlayCanvas для обработки ввода используется объект pc.Input, который предоставляет интерфейс для работы с клавишами, мышью, игровыми контроллерами и сенсорными экранами. Важно, что pc.Input предоставляет событие для каждого типа ввода, например, mousedown, mouseup, keydown, keyup и другие. Однако для интеграции нескольких источников ввода в единый контроллер потребуется более сложная структура.

Создание универсального контроллера ввода

Для создания универсального контроллера, который будет обрабатывать все виды ввода, можно создать отдельный класс. В этом классе нужно будет объединить все события ввода и предоставить абстракцию для удобной работы с ними.

Пример реализации универсального контроллера ввода:

var InputController = function (app) {
    this.app = app;
    this.input = app.input;

    this.mousePosition = new pc.Vec2();
    this.keyState = {};

    // Слушатели событий
    this.input.mouse.on(pc.EVENT_MOUSEMOVE, this.onMouseMove, this);
    this.input.mouse.on(pc.EVENT_MOUSEDOWN, this.onMouseDown, this);
    this.input.mouse.on(pc.EVENT_MOUSEUP, this.onMouseUp, this);
    this.input.keyboard.on(pc.EVENT_KEYDOWN, this.onKeyDown, this);
    this.input.keyboard.on(pc.EVENT_KEYUP, this.onKeyUp, this);
};

InputController.prototype = {
    onMouseMove: function (event) {
        this.mousePosition.set(event.x, event.y);
    },

    onMouseDown: function (event) {
        this.keyState['mouse' + event.button] = true;
    },

    onMouseUp: function (event) {
        this.keyState['mouse' + event.button] = false;
    },

    onKeyDown: function (event) {
        this.keyState[event.key] = true;
    },

    onKeyUp: function (event) {
        this.keyState[event.key] = false;
    },

    isKeyDown: function (key) {
        return this.keyState[key] || false;
    },

    isMouseButtonDown: function (button) {
        return this.keyState['mouse' + button] || false;
    },

    getMousePosition: function () {
        return this.mousePosition;
    }
};

В этом примере создается класс InputController, который объединяет обработку ввода с мыши и клавиатуры. Ключевые моменты:

  • Все события ввода (мышь и клавиатура) обрабатываются через методы onMouseMove, onMouseDown, onMouseUp, onKeyDown и onKeyUp.
  • Вся информация о текущем состоянии ввода (позиция мыши, нажатые клавиши и кнопки мыши) хранится в объекте keyState.
  • Методы isKeyDown и isMouseButtonDown позволяют проверить, нажата ли определенная клавиша или кнопка мыши.
  • Метод getMousePosition возвращает текущую позицию мыши.

Добавление поддержки геймпадов

Для расширения функциональности контроллера ввода и поддержки геймпадов, нужно добавить обработку ввода с устройств ввода, таких как джойстики. PlayCanvas предоставляет доступ к геймпадам через объект pc.Input.gamepads.

Добавление поддержки геймпада в контроллер можно реализовать следующим образом:

InputController.prototype.update = function () {
    var gamepads = this.input.gamepads;
    for (var i = 0; i < gamepads.length; i++) {
        var gamepad = gamepads[i];
        if (gamepad) {
            // Пример проверки состояния кнопок геймпада
            this.keyState['gamepad' + i] = gamepad.isPressed(pc.PAD_A);
        }
    }
};

Здесь добавлен метод update, который обновляет состояние геймпада, проверяя, нажата ли кнопка на устройстве. С помощью этого подхода можно легко интегрировать поддержку различных типов устройств ввода, включая геймпады.

Обработка комбинированного ввода

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

Пример улучшенной обработки комбинированного ввода:

InputController.prototype.update = function () {
    var gamepads = this.input.gamepads;
    var mouseState = this.input.mouse;
    var keyboardState = this.input.keyboard;

    // Проверка состояния клавиш
    if (keyboardState.isPressed(pc.KEY_W)) {
        console.log('Moving forward');
    }

    // Проверка состояния мыши
    if (mouseState.isPressed(pc.MOUSEBUTTON_LEFT)) {
        console.log('Left mouse button pressed');
    }

    // Проверка состояния геймпада
    for (var i = 0; i < gamepads.length; i++) {
        var gamepad = gamepads[i];
        if (gamepad && gamepad.isPressed(pc.PAD_B)) {
            console.log('Gamepad button B pressed');
        }
    }
};

В этом примере состояние клавиш, мыши и геймпадов проверяется параллельно, что позволяет эффективно реагировать на ввод с разных устройств одновременно.

Завершение работы с контроллером

После использования контроллера необходимо правильно завершить его работу, чтобы избежать утечек памяти или ошибок в обработке событий. Для этого необходимо отписаться от всех событий ввода и очистить все используемые ресурсы.

Пример завершения работы:

InputController.prototype.destroy = function () {
    this.input.mouse.off(pc.EVENT_MOUSEMOVE, this.onMouseMove, this);
    this.input.mouse.off(pc.EVENT_MOUSEDOWN, this.onMouseDown, this);
    this.input.mouse.off(pc.EVENT_MOUSEUP, this.onMouseUp, this);
    this.input.keyboard.off(pc.EVENT_KEYDOWN, this.onKeyDown, this);
    this.input.keyboard.off(pc.EVENT_KEYUP, this.onKeyUp, this);
};

Этот метод отписывает все обработчики событий ввода, что позволяет предотвратить утечки памяти.

Заключение

Создание универсального контроллера ввода позволяет значительно упростить управление устройствами ввода в проекте на PlayCanvas. С помощью такого подхода можно легко интегрировать поддержку множества типов устройств, таких как клавиатура, мышь, сенсорные экраны и геймпады, а также эффективно обрабатывать комбинированный ввод.