Web oyunlarınızı bir üst seviyeye çıkarmak için Gamepad API'yi nasıl kullanacağınızı öğrenin.
Chrome'un çevrimdışı sayfası olan paskalya yumurtası tarihte en kötü saklanan sırlardan biridir ([citation needed]
, ancak bu oyunun dramatik etkiye sahip olduğu iddia edildi). Boşluk tuşuna basarsanız veya mobil cihazlarda dinozora dokunursanız çevrimdışı sayfa, oynanabilir bir arcade oyunu haline gelir. Oyun oynamak istediğinizde internete bağlı olmanız gerekmediğini biliyor olabilirsiniz: Chrome'da about://dino
'e gidebilir veya meraklıysanız about://network-error/-106
'e göz atabilirsiniz. Ancak her ay 270 milyon Chrome dinozor oyunu oynandığını biliyor muydunuz?
Bilmenizin faydalı olabileceği ve farkında olmayabileceklerinizden biri de arcade modunda oyunu gamepad ile oynayabilmenizdir. Gamepad desteği, bu makalenin yazıldığı tarih itibarıyla yaklaşık bir yıl önce Reilly Grant tarafından yapılan bir taahhütte eklendi. Gördüğünüz gibi oyun, Chromium projesinin geri kalanı gibi tamamen açık kaynaktır. Bu gönderide, Gamepad API'nin nasıl kullanılacağını göstermek istiyorum.
Gamepad API'yi kullanma
Özellik algılama ve tarayıcı desteği
Gamepad API, hem masaüstü hem de mobil cihazlarda evrensel olarak mükemmel tarayıcı desteğine sahiptir. Aşağıdaki snippet'i kullanarak Gamepad API'nin desteklenip desteklenmediğini algılayabilirsiniz:
if ('getGamepads' in navigator) {
// The API is supported!
}
Tarayıcı, oyun kumandasını nasıl temsil eder?
Tarayıcı, gamepad'leri Gamepad
nesnesi olarak gösterir. Gamepad
aşağıdaki özelliklere sahiptir:
id
: Gamepad için bir tanımlayıcı dizesi. Bu dize, bağlı oyun kumandası cihazının markasını veya stilini tanımlar.displayId
: İlişkilendirilmiş birVRDisplay
öğesine aitVRDisplay.displayId
(varsa).index
: Gezinmedeki oyun kumandasının dizini.connected
: Gamepad'in sisteme bağlı olup olmadığını belirtir.hand
: Kumandanın hangi elde tutulduğunu veya hangi elide tutulacağını tanımlayan bir sıralama.timestamp
: Bu gamepad'in verilerinin en son güncellendiği zaman.mapping
: Bu cihazda kullanılan düğme ve eksen eşlemesidir ("standard"
veya"xr-standard"
).pose
: WebVR denetleyiciyle ilişkili duruş bilgilerini temsil eden birGamepadPose
nesnesi.axes
: Gamepad'in tüm eksenleri için-1.0
-1.0
aralığına göre doğrusal olarak normalleştirilmiş bir değer dizisi.buttons
: Oyun kumandasının tüm düğmelerinin düğme durumları dizisi.
Düğmelerin dijital (basılmış veya basılmamış) ya da analog (örneğin, %78'ine basılmış) olabileceğini unutmayın. Bu nedenle düğmeler, aşağıdaki özelliklerle GamepadButton
nesneleri olarak raporlanır:
pressed
: Düğmenin basılı durumu (düğmeye basılmışsatrue
, basılı değilsefalse
).touched
: Düğmenin dokunulduğu durum. Düğme dokunmayı algılayabiliyorsa bu özellik, düğmeye dokunuluyorsatrue
, aksi takdirdefalse
değerini alır.value
: Analog sensöre sahip düğmelerde bu özellik, düğmeye basılma miktarını gösterir ve0.0
–1.0
aralığına doğrusal olarak normalleştirilmiştir.hapticActuators
: Her biri denetleyicide bulunan dokunma geri bildirimi donanımını temsil edenGamepadHapticActuator
öğeleri içeren bir dizi.
Tarayıcınız ve gamepad'inize bağlı olarak karşılaşabileceğiniz bir diğer şey de vibrationActuator
mülküdür. İki tür titreşim efekti sağlar:
- Dual-Rumble: Oyun kumandasının her bir tutma noktasında birer tane olmak üzere alışılmadık dönen iki kütle aktüatörünün oluşturduğu dokunsal geribildirim efekti.
- Tetikleme-Rumble: Oyun kumandasının tetikleyicilerinin her birinde bir motor bulunan iki bağımsız motor tarafından oluşturulan dokunsal geribildirim etkisi.
Doğrudan spesifikasyondan alınan aşağıdaki şematik genel bakış, genel bir gamepad'deki düğmelerin ve eksenlerin haritalarını ve düzenini gösterir.
Oyun kumandası bağlandığında bildirim
Bir gamepad'in ne zaman bağlandığını öğrenmek için window
nesnesinde tetiklenen gamepadconnected
etkinliğini dinleyin. Kullanıcı, USB veya Bluetooth kullanarak bir oyun kumandasını bağladığında, oyun kumandasının ayrıntılarını uygun şekilde adlandırılmış gamepad
özelliğinde içeren bir GamepadEvent
tetiklenir.
Aşağıda, elimde bulunan bir Xbox 360 kumandasından alınmış bir örneği görebilirsiniz (Evet, retro oyunlara meraklıyım).
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"}
*/
});
Gamepad bağlantısı kesildiğinde bildirim
Oyun kumandası bağlantı kesintilerinden haberdar olmak, bağlantıların algılanmasına benzer şekilde gerçekleşir.
Bu kez uygulama gamepaddisconnected
etkinliğini dinler. Aşağıdaki örnekte, Xbox 360 kumandasının fişi çekildiğinde connected
değerinin false
olarak nasıl değiştiğine dikkat edin.
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
*/
});
Oyun döngünüzdeki oyun kumandası
Gamepad'i kullanmaya başlamak için navigator.getGamepads()
çağrısı yapılır. Bu çağrı, Gamepad
öğe içeren bir dizi döndürür. Chrome'daki dizinin uzunluğu her zaman dört öğe olarak sabitlenmiştir. Dörtten az oyun kumandası bağlanmışsa bu öğe yalnızca null
olabilir. Her zaman dizinin tüm öğelerini kontrol edin. Gamepad'lerin, slotlarını "hatırladığını" ve her zaman ilk kullanılabilir slotta bulunmayabileceğini unutmayın.
// When no gamepads are connected:
navigator.getGamepads();
// (4) [null, null, null, null]
Bir veya daha fazla gamepad bağlıysa ancak navigator.getGamepads()
hâlâ null
öğe bildiriyorsa her gamepad'in düğmelerinden birine basarak gamepad'i "uyandırmanız" gerekebilir. Daha sonra, aşağıdaki kodda gösterildiği gibi oyun döngünüzdeki oyun kumandası durumlarını yoklayabilirsiniz.
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();
Titreşim aktüatörü
vibrationActuator
mülkü, dokunma geri bildirimi amacıyla kuvvet uygulayabilen motorların veya diğer aktüatörlerin yapılandırmasına karşılık gelen bir GamepadHapticActuator
nesnesi döndürür. Dokunma etkileri Gamepad.vibrationActuator.playEffect()
çağrılarak oynatılabilir. Geçerli tek efekt türleri 'dual-rumble'
ve 'trigger-rumble'
'dir.
Desteklenen titreşim efektleri
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.
}
Çift titreşim
Çift titreşim, standart bir gamepad'in her koluna eksantrik dönen kütle titreşim motoru yerleştirilmiş bir dokunma yapılandırmasını ifade eder. Bu yapılandırmada, her iki motor da gamepad'in tamamını titreştirebilir. İki kütle eşit değildir. Böylece her birinin etkileri birleştirilerek daha karmaşık dokunma etkileri oluşturulabilir. Çift gürültülü efektler dört parametreyle tanımlanır:
duration
: Titreşim etkisinin süresini milisaniye cinsinden ayarlar.startDelay
: Titreşimin başlatılmasına kadar geçecek süreyi ayarlar.strongMagnitude
veweakMagnitude
: Daha ağır ve daha hafif eksantrik dönen kütle motorları için titreşim yoğunluğu seviyelerini0.0
-1.0
aralığına göre normalleştirilmiş olarak ayarlayın.
// 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,
});
};
Titreşimi tetikleme
Tetik titreşimi, gamepad'in tetikleyicilerinin her birinde bulunan bir motorla iki bağımsız motor tarafından oluşturulan dokunsal geri bildirim efektidir.
// 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,
});
};
İzin Politikası ile entegrasyon
Gamepad API spesifikasyonu, "gamepad"
dizesiyle tanımlanan politika tarafından kontrol edilen bir özelliği tanımlar. Varsayılan allowlist
değeri "self"
'dur. Bir dokümanın izin politikası, dokümandaki herhangi bir içeriğin navigator.getGamepads()
ürününe erişmesine izin verilip verilmeyeceğini belirler. Bir dokümanda devre dışı bırakılırsa dokümanda hiçbir içeriğin navigator.getGamepads()
kullanmasına izin verilmez ve gamepadconnected
ile gamepaddisconnected
etkinlikleri tetiklenmez.
<iframe src="index.html" allow="gamepad"></iframe>
Demo
Aşağıdaki örnekte bir gamepad test cihazı demosu yerleştirilmiştir. Kaynak koduna Glitch'ten ulaşabilirsiniz. USB veya Bluetooth kullanarak bir gamepad bağlayın ve düğmelerinden birine basarak veya eksenlerinden birini hareket ettirerek denemeyi deneyin.
Bonus: web.dev'de Chrome Dinozor'u oynayın
Bu sitede gamepad'inizle Chrome dinozor oyununu oynayabilirsiniz. Kaynak kodunu GitHub'da bulabilirsiniz.
trex-runner.js
içindeki oyun kumandası yoklama uygulamasına göz atın ve tuşlara basma işleminin nasıl taklit edildiğini inceleyin.
Chrome dino gamepad demosunun çalışması için Chrome dinozor oyununu ana Chromium projesinden çıkardım (Arnelle Ballane tarafından yapılan önceki bir çalışmayı güncelledim), bağımsız bir siteye yerleştirdim, eğme ve titreşim efektleri ekleyerek mevcut gamepad API uygulamasını genişlettim, tam ekran modu oluşturdum ve Mehul Satardekar karanlık mod uygulamasıyla katkıda bulundu. İyi oyunlar dileriz!
Faydalı bağlantı
Teşekkür ederiz
Bu doküman François Beaufort ve Joe Medley tarafından incelenmiştir. Gamepad API spesifikasyonu, Steve Agoston, James Hollyer ve Matt Reynolds tarafından düzenlenmiştir. Eski spesifikasyon editörleri Brandon Jones, Scott Graham ve Ted Mielczarek'tir. Oyun kumandası uzantıları spesifikasyonu, Brandon Jones tarafından düzenlenmiştir. Laura Torrent Puig tarafından oluşturulan hero resim.