JavaScript로 게임패드 지원 기능을 구현했습니다

브라우저 게임의 컨트롤러 입력을 역공학(reverse-engineering)하는 데 주말을 통째로 보냈습니다. 새벽 2시, 빈 배열을 멍하니 바라보고 있었습니다. 아무것도 나타나지 않았죠.

그 경험은 그 어떤 튜토리얼보다 브라우저 API와 하드웨어 폴링(polling)에 대해 더 많은 것을 가르쳐 주었습니다.

웹 게임 시장은 성장하고 있습니다. WebGL과 WebGPU 덕분에 브라우저 게임도 이제 높은 품질 수준에 도달했습니다. 플레이어들은 Xbox나 PS5 컨트롤러를 연결하자마자 바로 작동하기를 기대합니다.

게임, 접근성 도구 또는 커스텀 대시보드를 만든다면 HTML5 Gamepad API가 필요합니다. Chrome, Firefox, Edge에서 작동하며 별도의 라이브러리도 필요하지 않습니다.

제가 배운 내용은 다음과 같습니다:

  • 이 API는 연결 시에는 이벤트 기반(event-driven)이지만, 입력 시에는 폴링(polling) 방식입니다.
  • 입력을 지속적으로 읽으려면 requestAnimationFrame을 사용해야 합니다.
  • 사용자가 버튼을 누르기 전까지 브라우저는 컨트롤러를 표시하지 않습니다. 이는 하드웨어 핑거프린팅(fingerprinting)을 방지하기 위한 개인정보 보호 기능입니다.

데이터 관리하기:

  • gamepad.mapping을 사용하여 "standard" 레이아웃인지 확인하세요. 표준 매핑을 사용하면 버튼 0이 항상 하단 페이스 버튼(face button)이 되도록 보장할 수 있습니다.
  • gamepad.id를 확인하여 Vendor ID와 Product ID를 파악하세요. 이를 통해 Sony DualSense와 같은 특정 하드웨어를 식별할 수 있습니다.
  • 항상 데드존(deadzone) 필터를 구현하세요. 아날로그 스틱은 결코 완벽하게 중앙에 위치하지 않습니다. 데드존이 없으면 캐릭터나 카메라가 계속해서 드리프트(drift) 현상을 일으킵니다.

데드존을 처리하는 간단한 방법: If Math.abs(axis) > 0.1, then use the value.

햅틱 피드백: gamepad.vibrationActuator.playEffect를 사용하여 진동(rumble)을 발생시킬 수 있습니다. Chrome과 Edge에서는 잘 작동하지만, Firefox는 부분적으로만 지원하며 Safari는 지원하지 않습니다.

프로젝트를 위한 핵심 요약:

  • gamepadconnected 및 gamepaddisconnected 이벤트를 감지하세요.
  • 이전 버튼 상태를 추적하여 "누름(press)"과 "누르고 있음(hold)"을 구분하세요.
  • 미세한 스틱 움직임을 무시하기 위해 데드존 임계값을 사용하세요.
  • 여러 브라우저에서 테스트하세요.
  • navigator.getGamepads()는 스냅샷을 반환한다는 점을 기억하세요. 최신 데이터를 가져오려면 루프 내부에서 이 함수를 호출해야 합니다.

코드를 작성하기 전에 하드웨어를 테스트하고 싶다면 GamepadTester.pro를 사용해 보세요. API의 원시 데이터와 축(axis) 값을 실시간으로 보여줍니다.

출처: https://dev.to/grezalazar23453/i-built-gamepad-support-into-my-web-app-using-pure-javascript-heres-everything-i-learned-51a5