Як використовувати GamePad в браузері і в додатках для Windows на HTML і JavaScript?

Якщо ви розробляєте гри на HTML і JavaScript, то ця стаття для вас. Ми вже багато писали про те, що під Windows 8.x можна розробляти програми HTML/JS, причому, як правило, ви можете з легкістю просто взяти і використовувати ваш поточний движок, що працює в сучасних браузерах.



Просто як приклад: якщо ви робите платформер, то ви можете скористатися таким движком, як Phaser (до речі, він підтримує розробку на TypeScript!), або, нашим Platformer Гра StarterKit для Windows 8. До речі, якщо ви хочете зробити іграшку в жанрі Tower Defense, то у нас є ще один Starter Kit. А якщо ви хочете створити щось тривимірне використанням WebGL, то наше все для вас — це Babylon.js.


GamePad

Але в цій статті я не буду розповідати, як створити саму гру. Ми задамося іншим питанням: як підключити до гри для Windows 8.x або у браузері геймпад? Наприклад, ігровий контролер від Xbox 360, Xbox One:



Будемо вважати, що ви вже підключили сам геймпад до свого ПК (інструкція для Xbox 360, інструкція для Xbox One). Тепер давайте розберемося, що вам потрібно зробити, щоб додати його підтримку у своїй грі.

В якості прикладу я буду використовувати платформер RubbaRabbit з наведеного вище стартет-кита. Ми розглянемо два варіанти: гра для Windows 8.x і гра в браузері.


Гра для Windows 8.x на HTML і JavaScript
Щоб додати підтримку геймпада в гру на JavaScript під Windows 8.x вам знадобиться навчитися працювати з інтерфейсами XInput. Це може звучати страшнувато, тому що для цього потрібно зануритися в код на C++, але ми вже зробили практично все, що вам потрібно, щоб не перетинатися з ними безпосередньо.

Для роботи вам потрібно завантажити приклад XInput and JavaScript controller sketch. Всередині нього ви легко знайдете папочку з кодом на C++, в якій знаходиться проект бібліотеки-обв'язки над XInput, з якої ви в свою чергу зможете працювати в своїй грі на JavaScript.



Цей проект вам потрібно додати в свій солюшн з грою і додати посилання на нього всередині проекту для Windows 8.x:



При бажанні ви можете залізти всередину файлів на C++ і з'ясувати, що вони фактично виставляють назовні дуже простий інтерфейс доступу до контролеру: конструктор для отримання посилання на геймпад і функцію getState для отримання його поточного стану з проекцією на кнопки геймпада для Xbox.

Тепер потрібно додати підтримку геймпада у самій грі. Для цього, звичайно, потрібно зробити досить невеликі зміни в обробці введення з боку гравця.

Ігровий цикл

Як правило, в межах коду гри у вас є регулярний цикл, в рамках якого формується кожен наступний кадр гри. Для того, щоб зрозуміти, як змінилася ігрова обстановка, зокрема, ви перевіряєте, натиснув користувач певні кнопки.

В моєму випадку ігровий цикл задається всередині функції update:

/**
* simulation game loop step - called every frame during play
*/
this.update = function () {
...
}


Десь усередині цієї функції є обробка натискань на кнопки, яка виглядає приблизно так:

if (touchleft || jaws.pressed("left") || jaws.pressed("a")) { 
player.vx = -move_speed; player.flipped = 1; 
}
else if (touchright || jaws.pressed("right") || jaws.pressed("d")) { 
player.vx = +move_speed; player.flipped = 0; 
}

if (!player.attacking && (touchjump || jaws.pressed("up") || jaws.pressed("w") || jaws.pressed("space"))) { 
if (!player.jumping && player.can_jump) { 
sfxjump(); 
player.vy = jump_strength; 
player.jumping = true; 
player.can_jump = false; 
} 
}
else { 
player.can_jump = true; 
}


Як ви можете помітити, розробники движка вже подбали про те, що користувач може передавати команди не тільки з різних кнопок клавіатури, але і, наприклад, з віртуальних кнопок на сенсорному пристрої (змінні touchleft, touchright і тощо).

В цілому, швидше за все, у вашому коді повинні бути якісь змінні, що відповідають різним «ігровим діям» й акумулюють у собі різні способи введення для їх активації. Саме на роботу з такими змінними і буде зав'язано додавання підтримки геймпада.

Підтримка геймпада

Щоб додати підтримку геймпада залишилося зовсім небагато: потрібно ініціалізувати роботу з контролером при старті іграшки і далі регулярно отримувати його стан.

Для ініціалізації контролера ми створюємо об'єкт Controller через конструктор, доступний нам з підключеною раніше бібліотеки C++:

//Add Xbox Contoller support 
function initXboxpad() {
var controller = new GameController.Controller(0);

if (controller != null) {
updateState();
}

...
}


Далі нам потрібно з певною періодичністю оновлювати стан контролера, для цього опишемо функцію updateState, яка буде запитувати виклик себе на кожен кадр анімації:


//Add Xbox Contoller support 
function initXboxpad() {
var controller = new GameController.Controller(0);

// render loop
if (controller != null) {
updateState();
}

function updateState() {
var state = controller.getState();

if (state.connected) {
var x = state.leftThumbX / 32767;

touchleft = (x < -0.9);
touchright = (x > 0.9);

touchjump = state.a;
touchattack = state.x;
touchpause = state.start;
}
window.requestAnimationFrame(updateState);
} 
}


Це весь(!) код, який необхідно додати в іграшку, щоб вона навчилася взаємодіяти з геймпадом від Xbox 360. Не забудьте тільки при старті викликати саму функцію initXboxpad.



Зверніть увагу, що в даному випадку ми експлуатуємо» вже існуючі змінні, що акумулюють у собі команди від можливого сенсорного інтерфейсу, і оновлюємо їх в залежності від того, яке поточний стан елементів управління на геймпаді. Наприклад, якщо гравець натиснув кнопку «A», то відповідний стан state.a буде дорівнює true і ми проектуємо його на «стрибок» в грі.

До речі, через функцію setState геймпада ви можете змусити його вібрувати.

Гра в браузері
Тепер давайте подивимося, що ми можемо зробити в браузері. Для браузерів W3C розробляється спеціальний стандарт Gamepad API, який дозволить одноманітно працювати з різними типами ігрових геймпадів.

Стандарт передбачає, що є деяка «загальна модель», до якої можна звести різні ігрові контролери:


Якщо ви хочете прив'язати позначення конкретного типу пристрою (наприклад, геймпаду Xbox), вам це потрібно буде зробити самостійно, прописавши в своєму коді відповідне відображення.

Сам стандарт у цій статті занурюватися не буду, благо в інтернеті вже є достатня кількість оглядових статтею. Наприклад, ось документація від Mozilla. Єдине, що хочу тут відзначити — це те, що вона застаріла щодо припущення, що Gamepad API не підтримує Internet Explorer. справді, свіжих збірках Internet Explorer 11 Gamepad API вже підтримується.

В контексті даної статті про стандарт потрібно знати тільки одне: він надає доступ до сирим даними, розбитим по осях і нумерованих кнопкам. Щоб зрозуміти реальне відповідність, вам потрібно буде виконати певні розумові операції в своєму коді.

Ігровий цикл і код гри



Для демонстрації я продовжую використовувати той же приклад з стартер кита, тільки на цей раз створюю порожній веб-проект і копіюю у нього оригінальні вихідні файли. Так як вони не мають насправді ніякої зав'язки на платформу Windows, то гра просто працює в браузері:



Все інше поки залишається незмінними, і вірні ті ж самі припущення про ігровий цикл, які ми робили для проекту під Windows 8.

Підтримка геймпада

Щоб спростити собі роботу з геймпадом, я скористаюся готовим кодом з бібліотеки Babylon.js — babylon.gamepads.ts (GitHub). Ви можете просто скопіювати бібліотеку собі або зробити її форк.

Бібліотека робить кілька важливих речей:
  • вміє поверх Gamepad API симулювати подієву модель (якщо потрібно);
  • спрощує доступ до окремими елементами контролера (наприклад, об'єднує осі джойстика в один об'єкт);
  • розрізняє контролер Xbox, роблячи необхідне мені відображення узагальнених кнопок на конкретні.
Зверніть увагу, що бібліотека написана на TypeScript. Поруч ви також можете знайти скомпилированную версію для JavaScript. В моєму випадку я просто додаю бібліотеку всередину проекту, Visual Studio включає підтримку TypeScript і автоматично генерує js-файли при збереженні.

Не забудьте підключити бібліотеку на сторінку з грою:
<script src="js/babylon.gamepads.js"></script>


Далі схема підключення геймпада дуже схожа на те, що ми робили у випадку з Windows 8.x:

//Add Xbox Contoller support 
function initGamePad() {
var xboxpad;
function updateState() {
if (xboxpad != null && xboxpad.browserGamepad.connected) {
xboxpad.update();
touchleft = (xboxpad.leftStick.x < -0.9);
touchright = (xboxpad.leftStick.x > 0.9);
touchjump = (xboxpad.buttonA == 1);
touchattack = (xboxpad.buttonX == 1);
touchpause = (xboxpad.buttonStart == 1);
}
window.requestAnimationFrame(updateState);
}
var gamepadConnected = function (gamepad) {
if (gamepad instanceof BABYLON.Xbox360Pad) {
xboxpad = gamepad;
updateState();
}
};
var gamepads = new BABYLON.Gamepads(gamepadConnected);
}


Всередину функції BABYLON.Gamepads передається обробник події підключення геймпада у комп'ютера. Як бачите, додавання в проект поддежки геймпада — це приблизно 20 рядків коду!

Варіант коду з подієвою моделлю:
//Add Xbox Contoller support 
function initGamePad() {
var xboxpad;
var gamepadConnected = function (gamepad) {
if (gamepad instanceof BABYLON.Xbox360Pad) {
xboxpad = gamepad;
xboxpad.onleftstickchanged(function (values) {
var x = values.x;
touchleft = (x < -0.9);
touchright = (x > 0.9);
});
xboxpad.onbuttondown(function (button) {
switch (button) {
case BABYLON.Xbox360Button.A: 
touchjump = true;
break;
case BABYLON.Xbox360Button.X: 
touchattack = true;
break;
case BABYLON.Xbox360Button.Start: 
touchpause = true;
break;
}
});

xboxpad.onbuttonup(function (button) {
switch (button) {
case BABYLON.Xbox360Button.A: 
touchjump = false;
break;
case BABYLON.Xbox360Button.X: 
touchattack = false;
break;
case BABYLON.Xbox360Button.Start: 
touchpause = false;
break;
}
});
}
};
var gamepads = new BABYLON.Gamepads(gamepadConnected);
}


В результаті ми легко можемо керувати діями героя в грі прямо з підключеного геймпада:


Корисні посилання



Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.