HTML5 представил многие из необходимых компонентов для разработки многофункциональных интерактивных игр. Такие технологии, как
, WebGL, и
, наряду с реализациями JavaScript, имеют созрели до такой степени, что теперь они могут поддерживать многие задачи, ранее требовавшие нативного кода. Gamepad API — это способ для разработчиков и дизайнеров получать доступ и использовать геймпады и другие игровые контроллеры.
Gamepad API представляет новые события в объекте Window
для чтения состояние геймпада и контроллера (далее геймпад ). В дополнение к этим событиям API также добавляет объект Gamepad
, который можно использовать для запроса состояния подключенного геймпада, и navigator.getGamepads ()
, который можно использовать для получения списка геймпадов, известных странице.
Подключение к геймпаду
Когда к компьютеру подключен новый геймпад, страница с фокусом сначала получает событие gamepadconnected
. Если при загрузке страницы геймпад уже подключен, событие gamepadconnected
отправляется на страницу с фокусом, когда пользователь нажимает кнопку или перемещает ось.
В Firefox геймпады открываются для страницы только тогда, когда пользователь взаимодействует с одной, при этом страница отображается. Это помогает предотвратить использование геймпадов для снятия отпечатков пальцев пользователя. После взаимодействия с одним геймпадом другие подключенные геймпады будут автоматически видны.
Вы можете использовать gamepadconnected
следующим образом:
window.addEventListener ("gamepadconnected", function (e) {console.log ("Геймпад подключен с индексом% d:% s.% d кнопок,% d осей.", e .gamepad.index, напримерamepad.id, напримерamepad.buttons.length, напримерamepad.axes.length);});
Каждый геймпад имеет уникальный идентификатор связанный с ним, который доступен в свойстве события gamepad
.
Отключение геймпада
Когда геймпад отключен, и если страница ранее получала данные для этого геймпада (например, gamepadconnected
), второе событие отправляется в окно с фокусом, gamepaddisconnected
:
window.addEventListener ("gamepaddisconnected", function (e) {console.log ("Геймпад отключен от индекса% d:% s", например, геймпад .index, напримерamepad.id);});
Свойство index
геймпада будет уникальным для каждого устройства, подключенного к системе, даже если используется несколько контроллеров одного типа. Свойство index
также функционирует как индекс в Array
, возвращаемый Navigator.getGamepads ()
.
var gamepads = {}; функция gamepadHandler (событие, подключение) {var gamepad = event.gamepad; //Примечание://геймпад === navigator.getGamepads () [gamepad.index] if (подключение) {gamepads [gamepad. индекс] = геймпад; } else {удалить геймпады [gamepad.index]; }} window.addEventListener ("gamepadconnected", function (e) {gamepadHandler (e, true);}, false); window.addEventListener ("gamepaddisconnected", function (e) {gamepadHandler (e, false);}, false );
Этот предыдущий пример также демонстрирует, как свойство gamepad
может удерживаться после завершения события — метод, который мы будем использовать для определения состояния устройства. запрос позже.
Запрос объекта геймпада
Как видите, геймпад События, описанные выше, включают свойство gamepad
в объекте события, которое возвращает объект Gamepad
. Мы можем использовать это, чтобы определить, какой геймпад (то есть его идентификатор) вызвал событие, поскольку несколько геймпадов могут быть подключены одновременно. С помощью объекта Gamepad
мы можем сделать гораздо больше, в том числе удерживать ссылку на него и запрашивать его, чтобы узнать, какие кнопки и оси были нажаты в любой момент. Это часто желательно для игр или других интерактивных веб-страниц, которым необходимо знать состояние геймпада сейчас и при следующем срабатывании события.
Выполнение таких проверок, как правило, требует использования Gamepad в сочетании с циклом анимации (например, requestAnimationFrame
), где разработчики хотят принимать решения для текущего кадра на основе состояния геймпада или геймпадов.
Метод Navigator.getGamepads ()
возвращает массив всех устройств, которые в настоящее время видны на веб-странице, в виде объектов Gamepad
( первое значение всегда null
, поэтому null
будет возвращено, если нет подключенных геймпадов.) Затем это можно использовать для получения той же информации. Например, первый пример кода, приведенный выше, вы должны переписать, как показано ниже:
window.addEventListener ("gamepadconnected", function (e) {var gp = navigator.getGamepads () [egamepad.index]; console.log ("Геймпад подключен с индексом% d:% s.% d кнопок,% d осей.", gp.index, gp.id, gp.buttons.length, gp.axes .length);});
Свойства объекта Gamepad
следующие:
-
id
: строка, содержащая некоторую информацию о контроллере. Это не указано строго, но в Firefox он будет содержать три части информации, разделенные дефисом (-
): две четырехзначные шестнадцатеричные строки, содержащие поставщика USB и идентификатор продукта контроллера, и имя контроллера, предоставленное драйвером. Эта информация предназначена для того, чтобы вы могли найти сопоставление для элементов управления на устройстве, а также отобразить полезную обратную связь для пользователя. -
index
: целое число, которое уникален для каждого геймпада, подключенного к системе в данный момент. Это можно использовать для различения нескольких контроллеров. Обратите внимание, что отключение устройства и последующее подключение нового устройства может повторно использовать предыдущий индекс.. -
сопоставление
: строка, указывающая, переназначил ли браузер элементы управления на устройстве в известную компоновку. В настоящее время поддерживается только одна известная раскладка — стандартный геймпад. Если браузер может сопоставить элементы управления на устройстве с этим макетом, свойствоmapping
будет установлено в строкуstandard
. -
connected
: логическое значение, указывающее, подключен ли геймпад к системе. Если это так, значение равноTrue
; в противном случае этоFalse
. -
buttons
: массив объектовGamepadButton
представляющие кнопки, присутствующие на устройстве. У каждой кнопкиGamepadButton
есть нажатиеvalue
:- loaded — это логическое значение, указывающее, нажата ли кнопка в данный момент (
true
) или не нажата (false
). - Свойство
value
— это значение с плавающей запятой, используемое для включения представления аналоговых кнопок, таких как триггеры на многих современных геймпадах. Значения нормализованы до диапазона 0,0..1,0, где 0,0 представляет кнопку, которая не нажата, а 1,0 представляет кнопку, которая полностью нажата.
- loaded — это логическое значение, указывающее, нажата ли кнопка в данный момент (
-
axes
: массив, представляющий элементы управления с осями, присутствующими на устройстве (например, аналоговые джойстики). Каждая запись в массиве представляет собой значение с плавающей запятой в диапазоне от -1,0 до 1,0, представляющее положение оси от наименьшего значения (-1,0) до наибольшего значения (1.0). -
timestamp
: возвращаетDOMHighResTimeStamp
, представляющий последний раз, когда данные для этого геймпада были обновлены, что позволяет разработчикам определить, были ли осиnavigationStart
интерфейсаPerformanceTiming
. Значения монотонно увеличиваются, что означает, что их можно сравнивать для определения порядка обновлений, поскольку новые значения всегда будут больше или равны старым значениям. Обратите внимание, что это свойство в настоящее время не поддерживается в Firefox.
Примечание : объект Gamepad доступен в gamepadconnected
, а не сам объект Window
из соображений безопасности. Получив ссылку на него, мы можем запросить его свойства для получения информации о текущем состоянии геймпада. Незаметно для себя этот объект будет обновляться каждый раз при изменении состояния геймпада.
Использование информации о кнопках
Давайте посмотрим на простой пример, который отображает информацию о подключении для одного геймпада (он игнорирует последующие подключения геймпада) и позволяет вам перемещать мяч по экрану, используя четыре кнопки геймпада с правой стороны геймпада.. Вы можете просмотреть демонстрацию вживую и найти исходный код на Github.
Для начала мы объявляем некоторые переменные: абзац gamepadInfo
, в котором содержится информация о подключении. записанный в мяч
, который мы хотим переместить, переменную start
, которая действует как идентификатор для requestAnimation Frame
, переменные a
и b
, которые действуют как модификаторы положения для перемещения мяча, и сокращенные переменные, которые будут использоваться для requestAnimationFrame ( )
и cancelAnimationFrame ()
кроссбраузерные вилки.
var gamepadInfo = document.getElementById ("gamepad-info"); var ball = document.getElementById ("ball"); var start; var a = 0; var b = 0;
Затем мы используем подключенный геймпад
event для проверки подключения геймпада. Когда он подключен, мы захватываем геймпад с помощью Navigator.getGamepads ()
[0]
, выводим информацию о геймпаде в нашу информацию о геймпаде div
и запускает функцию gameLoop ()
, которая запускает весь процесс движения мяча.
window.addEventListener ( "gamepadconnected", функция (e) {var gp = navigator.getGamepads () [egamepad.index]; gamepadInfo.innerHTML = "Геймпад подключен по индексу" + gp.index + ":" + gp.id + ". Он имеет кнопки "+ gp.buttons.length +" и "+ gp.axes.length +" axes. "; GameLoop ();});
Теперь мы используем gamepaddisconnected
, чтобы проверить, отключен ли геймпад снова. Если это так, мы останавливаем цикл requestAnimationFrame ()
(см. Ниже) и возвращаем информацию геймпада к исходной.
окно .addEventListener ("gamepaddisconnected", function (e) {gamepadInfo.innerHTML = "Waiting for gamepad."; cancelRequestAnimationFrame (start);});
Здесь Chrome работает по-другому. Вместо того, чтобы постоянно сохранять последнее состояние геймпада в переменной, он хранит только моментальный снимок, поэтому, чтобы сделать то же самое в Chrome, вы должны продолжать его опрос, а затем использовать объект Gamepad
в коде только тогда, когда это доступно. Мы сделали это ниже, используя Window.setInterval ()
; как только объект становится доступным, выводится информация о геймпаде, запускается игровой цикл и интервал очищается с помощью Window.clearInterval ()
. Обратите внимание, что в более старых версиях Chrome Navigator.getGamepads ()
реализован с префиксом webkit
. Мы пытаемся обнаружить и обработать как версию с префиксом, так и стандартную версию функции для обратной совместимости.
var interval; if (! ('Ongamepadconnected' in window)) { //Нет доступных событий геймпада, вместо этого опрос. interval = setInterval (pollGamepads, 500);} function pollGamepads () {var gamepads = navigator.getGamepads? штурман. getGamepads (): (navigator.webkitGetGamepads? navigator.webkitGetGamepads: []); for (var i = 0; i
Теперь перейдем к основному циклу игры. При каждом выполнении цикла мы проверяем, нажата ли одна из четырех кнопок; если это так, мы соответствующим образом обновляем значения переменных перемещения a
и b
, а затем обновляем left
и top
, изменяя их значения на текущие значения a
и b
соответственно. Это дает эффект перемещения мяча по экрану. В текущих версиях Chrome (версия 34 на момент написания этой статьи) значения кнопок хранятся в виде массива двойных значений, а не объектов GamepadButton
. Это исправлено в разрабатываемых версиях.
После того, как все это будет сделано, мы используем наш requestAnimationFrame ()
для запроса следующего кадра анимации, выполняя gameLoop ()
снова.
function buttonPressed (b) {if (typeof (b) == "object") {return b.pressed; } return b == 1.0;} function gameLoop () {var gamepads = navigator.getGamepads? Navigator.getGamepads (): (navigator.webkitGetGamepads? navigator.webkitGetGamepads: []); если (! геймпады) {возврат; } var gp = gamepads [0]; если (buttonPressed (gp.buttons [0])) {b--; } иначе, если (buttonPressed (gp.buttons [2])) {b ++; } если (buttonPressed (gp.buttons [1])) {a ++; } else if (buttonPressed (gp.buttons [3])) {a--; } ball.style.left = a * 2 + "px"; ball.style.top = b * 2 + «пикс»; start = requestAnimationFrame (gameLoop);}
Полный пример: отображение состояния геймпада
В этом примере показано, как используйте объект Gamepad
, а также события gamepadconnected
и gamepaddisconnected
, чтобы отобразить состояние всех подключенных геймпадов в систему. Вы можете найти рабочую демонстрацию и посмотреть полный исходный код на Github.
var haveEvents = 'ongamepadconnected' в окне; var controllers = {}; function connecthandler (e) {addgamepad (например, геймпад);} функция addgamepad (геймпад) {контроллеры [gamepad.index] = геймпад; var d = document.createElement ("div"); d.setAttribute («идентификатор», «контроллер» + gamepad.index); var t = document.createElement ("h1"); t.appendChild (document.createTextNode ("геймпад:" + gamepad.id)); d.appendChild (t); var b = document.createElement ("div"); b.className = "кнопки"; для (var я = 0; я
Технические характеристики
Технические характеристики | Статус | Комментарий |
---|---|---|
Геймпад Определение ‘ Gamepad »в этой спецификации. |
Рабочий черновик | Первоначальное определение |
Совместимость с браузером
Таблицы BCD загружаются только в браузере
Таблица совместимости на этой странице генерируется из структурированных данных. Если вы хотите внести свой вклад в данные, посетите https://github.. com/mdn/browser-compat-data и отправьте нам запрос на перенос.