ดูวิธีใช้ Gamepad API เพื่อยกระดับเกมในเว็บของคุณขึ้นไปอีกขั้น
ไข่อีสเตอร์ของหน้าออฟไลน์ของ Chrome เป็นหนึ่งในความลับที่เลวร้ายที่สุดในประวัติศาสตร์ ([citation needed]
,
แต่กล่าวอ้างว่าใช้ผลลัพธ์ดราม่า) หากคุณกดแป้น Space หรือแป้นบนอุปกรณ์เคลื่อนที่
อุปกรณ์ แตะไดโนเสาร์ หน้าออฟไลน์จะกลายเป็นเกมอาร์เคดที่เล่นได้ คุณอาจทราบว่า
คุณไม่จำเป็นต้องออฟไลน์เมื่อรู้สึกอยากเล่นเกม เพราะใน Chrome คุณไปที่ตำแหน่งต่างๆ
ไปที่ about://dino
หรือถ้าอยากรู้จักคุณ ก็ไปที่ about://network-error/-106
แต่คุณทราบไหมว่า
ว่ามี
มีเกมไดโนเสาร์ Chrome ที่มีผู้เล่นมากถึง 270 ล้านเกมในแต่ละเดือน
อีกข้อเท็จจริงหนึ่งที่ใช้โต้แย้งได้มีประโยชน์กว่าและที่คุณไม่รู้มาก่อนคือ โหมดอาร์เคดที่คุณสามารถเล่นเกมด้วยเกมแพด เพิ่มการรองรับเกมแพดเมื่อประมาณ 1 ปีที่ผ่านมาเป็น ของการเขียนนี้ใน คอมมิตโดย Reilly Grant ดังที่คุณเห็น เกมจะเหมือนกับเกมอื่นๆ โปรเจ็กต์ Chromium เสร็จสมบูรณ์ โอเพนซอร์ส ใน โพสต์นี้ ผมต้องการแสดงวิธีใช้ API เกมแพด
ใช้ Gamepad API
การตรวจหาฟีเจอร์และการสนับสนุนเบราว์เซอร์
Gamepad API มีการรองรับเบราว์เซอร์ที่ยอดเยี่ยมในทั้ง 2 แพลตฟอร์ม ทั้งเดสก์ท็อปและอุปกรณ์เคลื่อนที่ คุณตรวจสอบได้ว่ามีการรองรับ Gamepad API หรือไม่โดยใช้ข้อมูลโค้ดต่อไปนี้
if ('getGamepads' in navigator) {
// The API is supported!
}
เบราว์เซอร์แสดงถึงเกมแพดอย่างไร
เบราว์เซอร์แสดงเกมแพดเป็น Gamepad
ออบเจ็กต์ Gamepad
มีพร็อพเพอร์ตี้ต่อไปนี้
id
: สตริงการระบุของเกมแพด สตริงนี้ระบุแบรนด์หรือรูปแบบของ อุปกรณ์เกมแพดที่เชื่อมต่ออยู่displayId
:VRDisplay.displayId
จากVRDisplay
ที่เกี่ยวข้อง (หากเกี่ยวข้อง)index
: ดัชนีของเกมแพดในเครื่องมือนำทางconnected
: ระบุว่าเกมแพดยังเชื่อมต่อกับระบบอยู่ไหมhand
: Enum เป็นตัวกำหนดมือที่ตัวควบคุมถืออยู่หรือที่มีแนวโน้มที่จะถือมากที่สุด นิ้วtimestamp
: ครั้งล่าสุดที่อัปเดตข้อมูลสำหรับเกมแพดนี้mapping
: การแมปปุ่มและแกนที่ใช้สำหรับอุปกรณ์นี้ ได้แก่"standard"
หรือ"xr-standard"
pose
: ออบเจ็กต์GamepadPose
ซึ่งแสดงข้อมูลท่าทางที่เชื่อมโยงกับตัวควบคุม WebVRaxes
: อาร์เรย์ของค่าสำหรับแกนเกมแพดทุกแกน ซึ่งแปลงเป็นรูปแบบมาตรฐานเชิงเส้นไว้ที่ช่วง-1.0
-1.0
buttons
: อาร์เรย์สถานะของปุ่มทุกปุ่มของเกมแพด
โปรดทราบว่าปุ่มต่างๆ อาจเป็นปุ่มดิจิทัล (กดหรือไม่กด) หรือแอนะล็อก (เช่น เมื่อกด 78%) ช่วงเวลานี้
คือสาเหตุที่ปุ่มมีการรายงานเป็นออบเจ็กต์ GamepadButton
โดยมีแอตทริบิวต์ต่อไปนี้
pressed
: สถานะการกดของปุ่ม (true
หากกดปุ่ม และfalse
หากไม่ได้กดtouched
: สถานะการแตะของปุ่ม หากปุ่มสามารถตรวจจับการแตะได้ พร็อพเพอร์ตี้คือtrue
หากมีการแตะปุ่ม และfalse
หากไม่ใช่value
: สำหรับปุ่มที่มีเซ็นเซอร์แอนะล็อก คุณสมบัตินี้จะแสดงปริมาณ มีการกดปุ่มแล้ว ปรับให้เป็นเส้นตรงให้เป็นช่วงของ0.0
–1.0
แล้วhapticActuators
: อาร์เรย์ที่มีGamepadHapticActuator
โดยแต่ละออบเจ็กต์จะแสดงฮาร์ดแวร์การตอบสนองแบบรู้สึกได้ที่มีอยู่ในตัวควบคุม
สิ่งหนึ่งที่คุณอาจพบขึ้นอยู่กับเบราว์เซอร์และเกมแพดที่มี
เป็นพร็อพเพอร์ตี้ vibrationActuator
โดยทำให้เกิดเอฟเฟกต์กระตุก 2 แบบ ดังนี้
- การตอบสนองแบบรู้สึกได้แบบ 2 จังหวะ: เอฟเฟกต์การตอบสนองแบบรู้สึกได้ที่เกิดจากตัวขับเคลื่อนมวลชนแบบหมุนศูนย์กลาง 2 ตัว โดย 1 ตัวในด้ามจับแต่ละข้างของเกมแพด
- ทริกเกอร์-รูมเบิล: เอฟเฟกต์การตอบสนองแบบรู้สึกได้ที่เกิดจากมอเตอร์อิสระ 2 ตัว โดยมีมอเตอร์ 1 ตัวอยู่ในทริกเกอร์ของเกมแพดแต่ละตัว
ภาพรวมสคีมาต่อไปนี้ถ่ายไว้ ตรงกับข้อกำหนด แสดงการแมปและการจัดเรียงปุ่มและแกนบนเกมแพดทั่วไป
การแจ้งเตือนเมื่อเชื่อมต่อเกมแพด
หากต้องการเรียนรู้เมื่อมีการเชื่อมต่อเกมแพด ให้ฟังเหตุการณ์ gamepadconnected
ที่ทริกเกอร์บน
window
ออบเจ็กต์ เมื่อผู้ใช้เชื่อมต่อเกมแพด ซึ่งอาจเป็นการใช้ USB หรือบลูทูธ
GamepadEvent
เริ่มทำงานที่มีรายละเอียดของเกมแพดในพร็อพเพอร์ตี้ gamepad
ที่ตั้งชื่อได้อย่างเหมาะสม
ในตัวอย่างต่อไปนี้ คุณจะเห็นตัวอย่างจากคอนโทรลเลอร์ Xbox 360 ที่ฉันเคยนอนอยู่ (ใช่ ฉันอยู่ใน
เกมย้อนยุค)
window.addEventListener('gamepadconnected', (event) => {
console.log('✅ 🎮 A gamepad was connected:', event.gamepad);
/*
gamepad: Gamepad
axes: (4) [0, 0, 0, 0]
buttons: (17) [GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton]
connected: true
id: "Xbox 360 Controller (STANDARD GAMEPAD Vendor: 045e Product: 028e)"
index: 0
mapping: "standard"
timestamp: 6563054.284999998
vibrationActuator: GamepadHapticActuator {type: "dual-rumble"}
*/
});
การแจ้งเตือนเมื่อเกมแพดถูกยกเลิกการเชื่อมต่อ
การได้รับการแจ้งเตือนการขาดการเชื่อมต่อเกมแพดจะเกิดขึ้นในลักษณะเดียวกับวิธีตรวจจับการเชื่อมต่อ
ครั้งนี้แอปรอฟังเหตุการณ์ gamepaddisconnected
โปรดสังเกตวิธีในตัวอย่างต่อไปนี้
ตอนนี้ connected
คือ false
เมื่อฉันถอดปลั๊กคอนโทรลเลอร์ Xbox 360
window.addEventListener('gamepaddisconnected', (event) => {
console.log('❌ 🎮 A gamepad was disconnected:', event.gamepad);
/*
gamepad: Gamepad
axes: (4) [0, 0, 0, 0]
buttons: (17) [GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton, GamepadButton]
connected: false
id: "Xbox 360 Controller (STANDARD GAMEPAD Vendor: 045e Product: 028e)"
index: 0
mapping: "standard"
timestamp: 6563054.284999998
vibrationActuator: null
*/
});
เกมแพดใน Game Loop ของคุณ
การถือเกมแพดจะเริ่มต้นด้วยการเรียก navigator.getGamepads()
ซึ่งแสดงผลอาร์เรย์
ที่มี Gamepad
รายการ อาร์เรย์ใน Chrome มีความยาวคงที่ที่ 4 รายการเสมอ หากเป็น 0 หรือน้อยกว่า
เกมแพดเชื่อมต่ออยู่มากกว่า 4 เครื่อง รายการหนึ่งอาจจะเป็น null
อย่าลืมตรวจสอบทุกรายการ
อาร์เรย์และระมัดระวังว่าเกมแพดจะ "จำ" ช่องของครีเอเตอร์รายดังกล่าวและอาจไม่ได้แสดงที่
ที่ว่างแรก
// When no gamepads are connected:
navigator.getGamepads();
// (4) [null, null, null, null]
หากมีการเชื่อมต่อเกมแพดอย่างน้อย 1 รายการ แต่ navigator.getGamepads()
ยังคงรายงาน null
รายการ
คุณอาจต้อง "ปลุก" แต่ละเกมแพดด้วยการกดปุ่มใดๆ ของเกมแพด จากนั้นคุณจะสำรวจเกมแพดได้
สถานะใน Game Loop ของคุณดังที่แสดงในโค้ดต่อไปนี้
const pollGamepads = () => {
// Always call `navigator.getGamepads()` inside of
// the game loop, not outside.
const gamepads = navigator.getGamepads();
for (const gamepad of gamepads) {
// Disregard empty slots.
if (!gamepad) {
continue;
}
// Process the gamepad state.
console.log(gamepad);
}
// Call yourself upon the next animation frame.
// (Typically this happens every 60 times per second.)
window.requestAnimationFrame(pollGamepads);
};
// Kick off the initial game loop iteration.
pollGamepads();
ตัวดำเนินการการสั่น
พร็อพเพอร์ตี้ vibrationActuator
จะแสดงผลออบเจ็กต์ GamepadHapticActuator
ซึ่งสอดคล้องกับ
การกำหนดค่ามอเตอร์หรือแอคชูเอเตอร์อื่นๆ ที่สามารถใช้แรงเพื่อวัตถุประสงค์แบบรู้สึกได้
ความคิดเห็น เล่นเอฟเฟกต์การโต้ตอบการสัมผัสได้โดยเรียกใช้ Gamepad.vibrationActuator.playEffect()
มีเพียง
ประเภทเอฟเฟกต์ที่ถูกต้องคือ 'dual-rumble'
และ 'trigger-rumble'
เอฟเฟกต์รุมเบิลที่รองรับ
if (gamepad.vibrationActuator.effects.includes('trigger-rumble')) {
// Trigger rumble supported.
} else if (gamepad.vibrationActuator.effects.includes('dual-rumble')) {
// Dual rumble supported.
} else {
// Rumble effects aren't supported.
}
Dual Rumble
การกดปุ่ม 2 เส้นจะอธิบายการกำหนดค่าแบบรู้สึกได้ มอเตอร์สั่นแบบมวลหมุนประหลาดในด้ามจับแต่ละด้านของเกมแพดมาตรฐาน ในการกำหนดค่าแบบนี้ มอเตอร์ตัวใดตัวหนึ่งก็สามารถสั่นทั้งเกมแพดได้ มวลสองมวลไม่เท่ากัน ดังนั้นค่า สามารถรวมกันเพื่อสร้างผลกระทบแบบรู้สึกได้ที่ซับซ้อนยิ่งขึ้น เอฟเฟกต์แบบ 2 จังหวะ กำหนดโดยพารามิเตอร์ 4 ตัว ได้แก่
duration
: ตั้งค่าระยะเวลาของเอฟเฟ็กต์การสั่นเป็นมิลลิวินาทีstartDelay
: ตั้งค่าระยะหน่วงเวลาจนกว่าจะเริ่มการสั่นstrongMagnitude
และweakMagnitude
: ตั้งค่าระดับความเข้มของการสั่นสำหรับหนักขึ้นและ มอเตอร์มวลการหมุนรอบศูนย์กลางที่ใช้ไฟน้อยกว่า ซึ่งปรับให้เป็นช่วงมาตรฐานที่ช่วง0.0
–1.0
// This assumes a `Gamepad` as the value of the `gamepad` variable.
const dualRumble = (gamepad, delay = 0, duration = 100, weak = 1.0, strong = 1.0) => {
if (!('vibrationActuator' in gamepad)) {
return;
}
gamepad.vibrationActuator.playEffect('dual-rumble', {
// Start delay in ms.
startDelay: delay,
// Duration in ms.
duration: duration,
// The magnitude of the weak actuator (between 0 and 1).
weakMagnitude: weak,
// The magnitude of the strong actuator (between 0 and 1).
strongMagnitude: strong,
});
};
ทริกเกอร์ตะลุมบอน
ทริกเกอร์ตะลุมบอนคือเอฟเฟกต์การตอบสนองแบบรู้สึกได้ที่เกิดจากมอเตอร์อิสระ 2 ตัว โดยมีมอเตอร์ 1 ตัวอยู่ในทริกเกอร์ของเกมแพดแต่ละตัว
// This assumes a `Gamepad` as the value of the `gamepad` variable.
const triggerRumble = (gamepad, delay = 0, duration = 100, weak = 1.0, strong = 1.0) => {
if (!('vibrationActuator' in gamepad)) {
return;
}
// Feature detection.
if (!('effects' in gamepad.vibrationActuator) || !gamepad.vibrationActuator.effects.includes('trigger-rumble')) {
return;
}
gamepad.vibrationActuator.playEffect('trigger-rumble', {
// Duration in ms.
duration: duration,
// The left trigger (between 0 and 1).
leftTrigger: leftTrigger,
// The right trigger (between 0 and 1).
rightTrigger: rightTrigger,
});
};
การผสานรวมกับนโยบายสิทธิ์
ข้อกำหนดของ Gamepad API กำหนด
ฟีเจอร์ที่ควบคุมตามนโยบายที่ระบุโดย
สตริง "gamepad"
ค่าเริ่มต้นของ allowlist
คือ "self"
นโยบายสิทธิ์ของเอกสารจะกำหนด
มีเนื้อหาในเอกสารนั้นได้รับอนุญาตให้เข้าถึง navigator.getGamepads()
หรือไม่ หากปิดใช้ใน
เอกสาร เอกสาร จะไม่ได้รับอนุญาตให้ใช้ navigator.getGamepads()
และจะไม่
เหตุการณ์ gamepadconnected
และ gamepaddisconnected
จะเริ่มทำงาน
<iframe src="index.html" allow="gamepad"></iframe>
สาธิต
การสาธิตเกมแพดฝังอยู่ในตัวอย่างต่อไปนี้ ซอร์สโค้ด พร้อมใช้งานใน Glitch ทดลองใช้การสาธิตด้วยการเชื่อมต่อ เกมแพดที่ใช้ USB หรือบลูทูธ และการกดปุ่มใดๆ ของเกมแพดหรือขยับแกนใดก็ได้
โบนัส: เล่นไดโนเสาร์ Chrome ใน web.dev
คุณสามารถเล่นไดโนเสาร์ Chrome ด้วยเกมแพดใน
ที่ยิ่งใหญ่มาก ดูซอร์สโค้ดได้ใน GitHub
ลองดูการใช้งานการสำรวจเกมแพดใน
trex-runner.js
และสังเกตวิธีจำลองการกดแป้นต่างๆ
สำหรับการสาธิตการใช้งานเกมแพดไดโนเสาร์ Chrome เกมไดโนเสาร์ Chrome จากโครงการ Chromium หลัก (การอัปเดต ความพยายามก่อนหน้านี้โดย Arnelle Ballane) มาวางบนเว็บไซต์แบบสแตนด์อโลน ขยาย การใช้ Gamepad API ที่มีอยู่ด้วยการเพิ่มเอฟเฟกต์การลดเสียงและการสั่น เป็นการสร้างแบบเต็มหน้าจอ และ Mehul Satardekar มีส่วนร่วมในโหมดมืด การใช้งานของคุณ ขอให้สนุกกับการเล่นเกม
ลิงก์ที่มีประโยชน์
กิตติกรรมประกาศ
เอกสารนี้ได้รับการตรวจสอบโดย François Beaufort และ Joe Medley ข้อกำหนดของ Gamepad API ได้รับการแก้ไขโดย Steve Agoston James Hollyer และ Matt Reynolds ข้อกำหนดเดิมของผู้แก้ไขสเปค Brandon Jones, Scott Graham และ Ted Mielczarek ข้อกำหนดส่วนขยายเกมแพดแก้ไขโดย Brandon Jones รูปภาพหลักโดย Laura Torrent Puig