WebRTC'yi PeerJS ile Evcilleştirmek: Basit Bir P2P Web Oyunu Yapmak
Yayınlanan: 2022-03-11WebRTC, web tarayıcıları arasında gerçek zamanlı iletişim sağlayan bir teknolojidir. Nispeten yeni ve API tanımı hala bir taslak olarak kabul ediliyor. WebRTC'nin henüz tüm büyük web tarayıcıları tarafından desteklenmemesi gerçeğiyle birleştiğinde (ve destekleyenler arasında, bazıları bu teknolojinin her özelliğini desteklemez), bu, WebRTC'yi herhangi bir kritik görev uygulaması için kullanmayı nispeten zorlaştırır. . Ya da öyle sanırdınız!
Mayıs 2011'de Google tarafından ilk kez tanıtıldığından beri WebRTC, birçok modern web uygulamasında kullanılmıştır. Birçok modern web tarayıcısının temel özelliği olan web uygulamaları, birçok yönden gelişmiş kullanıcı deneyimi sunmak için bu teknolojiden sorunsuz bir şekilde yararlanabilir. Şişirilmiş tarayıcı eklentileri gerektirmeyen ve eşler arası (P2P) ağlardan yararlanabilen (her veriyi bir sunucu aracılığıyla iletmezken) video akışı veya konferans uygulamaları, tüm şaşırtıcı şeylerin yalnızca bir parçasıdır. WebRTC ile elde edilebilir.
Bu yazıda, Connect Four'un basit bir P2P web oyunu yapmak için WebRTC'nin nasıl kullanılabileceğine bir göz atacağız. WebRTC'nin çeşitli pürüzlü kenarları ve uygulama farklılıkları üzerinde çalışmak için harika bir JavaScript kitaplığı kullanacağız: PeerJS.
WebRTC üzerinden veri
Başlamadan önce, WebRTC'nin yalnızca ses ve video akışlarını iletmekle ilgili olmadığını anlamak önemlidir. Ayrıca P2P veri kanalları için destek sağlar. Bu kanalların iki çeşidi vardır: güvenilir ve güvenilmez. Tahmin edilebileceği gibi, güvenilir veri kanalları mesajların iletildiğini ve sırayla iletildiğini garanti ederken, güvenilmez kanallar böyle bir garanti vermez.
Ayrıca, WebRTC veri kanalları, tipik bir WebRTC eş bağlantısının gerektirdiğinden başka hiçbir özel altyapı kurulumu gerektirmez: eşler arasındaki bağlantıyı koordine etmek için bir sinyal sunucusu, eşlerin genel kimliğini belirlemek için bir STUN sunucusu ve isteğe bağlı olarak bir TURN sunucusu eşler arasında doğrudan bir bağlantı kurulamıyorsa, eşler arasında mesajları yönlendirmek için (örneğin, her iki eş de NAT'ların arkasında olduğunda). Bu kısaltmalar tanıdık geliyorsa, bunun nedeni WebRTC'nin mümkün olan her yerde mevcut teknolojileri yeniden kullanmasıdır.
Bu, çok oyunculu oyunlar, içerik teslimi ve dosya paylaşımı dahil ancak bunlarla sınırlı olmamak üzere WebRTC'nin çok daha fazla kullanım örneğinin kapısını açar. Yine, hepsi herhangi bir aracı sunucuya ihtiyaç duymadan ve dolayısıyla daha düşük gecikmelerle.
Basit web oyunumuzda, oyuncu hareketlerini ileri geri iletmek için iki web tarayıcısı arasında bir veri kanalı kullanacağız.
PeerJS ile tanışın
PeerJS, WebRTC uygulamasını tarayıcınızda alır ve etrafına basit, tutarlı ve zarif bir API sarar. Daha önceki tarayıcıların WebRTC uygulamasında çeşitli delikleri kapatır. Örneğin, Chrome 30 veya daha eski sürümlerde yalnızca güvenilir olmayan veri kanalları mevcuttu. PeerJS, güvenilir veri kanalları kullanacak şekilde yapılandırılmışsa, bu eski tarayıcılar için bir şim kullanır. Bu, güvenilir kanalların yerel uygulaması kadar performanslı olmasa da yine de işe yarayacaktır.
PeerJS ile eşleri belirlemek daha da basittir. Her eş, yalnızca bir kimlik kullanılarak tanımlanır. Eşin kendisini seçebileceği veya bir sunucunun oluşturmasını sağlayabileceği bir dize. WebRTC, eşler arası iletişim vaat etse de, bağlantı aracısı olarak hareket etmek ve sinyallemeyi yönetmek için yine de bir sunucuya ihtiyacınız var. PeerJS, bulutta barındırılan sürümlerini (şu anda ücretsizdir ve bazı sınırlamalarla birlikte gelir) kullanmak istemiyorsanız, bu bağlantı aracı sunucusu PeerJS Sunucusunun (Node.js'de yazılmıştır) açık kaynaklı bir uygulamasını sağlar.
Four Goes P2P'yi bağlayın
Artık WebRTC ile çalışmak için bir güven kaynağımız olduğuna göre, yani PeerJS, basit bir Node.js/Express uygulaması oluşturarak başlayalım.
npm init npm install express --save npm install jade --save npm install peer --save
Bunu yalnızca PeerJS Sunucusunu barındırmak ve bir sayfa ve ön uç varlıkları sunmak için kullanacağız. Yalnızca tek bir sayfa sunmamız gerekecek ve bu iki bölüm içerecek: düz bir ana menü ve 7'ye 6 Connect Four ızgarası.
PeerJS Sunucusu
Kendi PeerJS Sunucumuzu barındırmak gerçekten çok kolay. GitHub'daki resmi depoda, bir PeerJS Sunucusu örneğini Heroku'ya dağıtmak için tek tıklamalı bir düğme bile bulunur.
Bizim durumumuzda, Node.js uygulamamızda bir ExpressPeerServer örneği oluşturmak ve bunu “/peerjs” konumunda sunmak istiyoruz:
var express = require('express') var app = express() // … Configure Express, and register necessary route handlers srv = app.listen(process.env.PORT) app.use('/peerjs', require('peer').ExpressPeerServer(srv, { debug: true }))
PeerJS İstemcisi
PeerJS Sunucusu hazır ve çalışır durumdayken, istemci tarafına geçiyoruz. Daha önce tartışıldığı gibi, PeerJS benzersiz kimlikleri olan eşleri tanımlar. Bu kimlikler PeerServer tarafından her eş için otomatik olarak oluşturulabilir veya Peer nesnelerini somutlaştırırken her eş için bir tane seçebiliriz.
var peer = new Peer(id, options)
Burada, sunucunun bizim için bir tane oluşturmasını istiyorsak id tamamen atlanabilir. Bizim durumumuzda, yapmak isteyeceğimiz şey bu. PeerServer, verdiği kimliklerin benzersiz olmasını sağlayacaktır. İkinci argüman, options , genellikle anahtar içeren bir nesnedir (bulutta barındırılan PeerServer kullanıyorsanız API anahtarı veya PeerServer'ı kendiniz barındırıyorsanız host , port , path vb.).
var peer = new Peer({ host: location.hostname, port: location.port || (location.protocol === 'https:' ? 443 : 80), path: '/peerjs' })
İki PeerJS eşleri arasında bağlantı kurabilmek için eşlerden birinin diğer eşin kimliğini bilmesi gerekir. İşleri basit tutmak adına, WebRTC üzerinden Connect Four uygulamamızda, oyunu başlatan oyuncunun akran kimliğini rakibiyle paylaşmasını isteyeceğiz. Hedef eş kimliği biliniyorsa, tek ihtiyacımız olan peer.connect(destId) öğesine yapılan basit bir çağrıdır:

var conn = peer.connect(destId)
Hem Peer nesnesi hem de peer.connect(destId) tarafından döndürülen DataConnection nesnesi, dinlemeye değer gerçekten yararlı bazı olaylar yayar. Bu öğreticinin amaçları doğrultusunda, özellikle DataConnection nesnesinin 'data' olayı ve her iki nesnenin de 'hata' olaylarıyla ilgileniyoruz.
Bağlantının diğer ucuna veri göndermek için conn.send(data) komutunu çağırmanız yeterlidir:
conn.send('hello')
Buradaki ihtiyaçlarımız için biraz fazla olsa da, PeerJS, BinaryPack formatında kodladıktan sonra eşler arasında veri iletir. Bu, eşlerin dizeleri, sayıları, dizileri, nesneleri ve hatta blobları iletmesine olanak tanır.
Gelen verileri almak için conn'de 'data' olayını dinlemeniz yeterlidir:
conn.on('data', function(data) { // data === 'hello' })
Ve ihtiyacımız olan hemen hemen hepsi bu!
Oyun Mantığı
Oyuna başlayan ilk oyuncuya, rakibiyle paylaşabilecekleri PeerJS tarafından oluşturulan akran kimliği gösterilir. Bir rakip, ilk oyuncunun akran kimliğini kullanarak oyuna katıldığında, ilk oyuncunun hamle yapmasına izin verilir.
Basit kurallar ve mekaniklerden oluşan bir oyun olan Connect Four'un tek bir hamle türü vardır: her oyuncu sırayla bir sütun seçmeli ve içine bir disk bırakmalıdır. Bu, bir eşin iletişim kurması gereken tek şeyin, mevcut oynatıcının diskini bırakmayı seçtiği sütun numarası olduğu anlamına gelir. Bu bilgiyi iki öğeli bir dizi olarak ileteceğiz: bir 'hareket' dizesi ve bir sayı - 0- soldan sütunun tabanlı dizini.
Bir oyuncu bir sütuna her tıkladığında:
if(!turn) { // it is not the current player's turn return } var i // i = chosen column index if(grid[i].length == 6) { // the column doesn't have any more space available return } // track player's move locally grid[i].push(peerId) // end current player's turn turn = false conn.send(['move', i])
Bu hareket verilerini rakibe gönderdikten sonra oyunun durumunu yerel olarak güncelliyoruz. Bu, mevcut oyuncunun kazanıp kazanmadığını veya oyunun berabere bitip bitmediğini belirlemeyi içerir.
Bu hareket verilerinin alıcı tarafında:
if(turn) { // ignore incoming move data when it is the current player's turn return } var i = data[1] if(grid[i].length == 6) { // ignore incoming move data when it is invalid return } // track opponent's move locally grid[i].push(opponent.peerId) // activate current player's turn turn = true
Ve doğal olarak, bundan sonra oyunun durumunu yerel olarak güncelleriz, rakibin kazanıp kazanmadığını veya oyunun berabere bitip bitmediğini belirleriz.
Gelen veriler üzerinde akıl sağlığı kontrollerini nasıl yapmamız gerektiğine dikkat edin. WebRTC tabanlı oyunlarda, taşıma verilerini doğrulayan aracı sunucu ve sunucu tabanlı oyun mantığımız olmadığı için bu önemlidir.
Parçacıkları basit tutmak için, kullanıcı arayüzünü güncelleyen kod satırları çıkarılmıştır. İstemci tarafı JavaScript'in tam kaynak kodunu burada bulabilirsiniz.
Her Şeyi Bağlamak
Hepsini birleştirmek için iki bölümden oluşan basit bir sayfa oluşturuyoruz. Sayfa yüklendiğinde ana menüyü içeren bölüm gösterilir, oyun ızgarasını içeren bölüm gizli tutulur.
section#menu div.animated.bounceIn div h1 Connect Four br div.no-support() div.alert.alert-warning p Unfortunately, your web browser does not <a href="http://iswebrtcreadyyet.com">support WebRTC</a> div a.btn.btn-primary.btn-lg(href='#start') Start | a.btn.btn-default.btn-lg(href='#join') Join section#game() div div h1 Connect Four br table.table.grid tbody for i in [0, 1, 2, 3, 4, 5] tr for j in [0, 1, 2, 3, 4, 5, 6] td div.slot br div.alert.alert-info p
Bu DOM öğelerinin güzel görünmesini sağlamak bu öğreticinin kapsamı dışındadır. Bu nedenle, güvenilir yol arkadaşımız Bootstrap'a başvuracağız ve üzerinde biraz hafif şekillendirme yapacağız.
İlk oyuncu “Başlat” düğmesine tıkladığında, oyuncunun akran kimliğiyle birlikte oyun tablosu ortaya çıkar. Oyuncu daha sonra bu akran kimliğini rakibiyle paylaşabilir.
İkinci oyuncu, ardından “Katıl” düğmesine tıklayabilir, ilk oyuncunun eş kimliğini girebilir ve oyuna başlayabilir.
Denemek
Bu örnek uygulamayı https://arteegee.herokuapp.com adresinde deneyebilirsiniz.
Veya depoyu GitHub'dan klonlayabilir, NPM bağımlılıklarını yükleyebilir ve yerel olarak deneyebilirsiniz:
git clone https://github.com/hjr265/arteegee.git cd arteegee npm install PORT=5000 npm start
Sunucu çalışmaya başladığında, web tarayıcınızı http://localhost:5000'e yönlendirebilir, bir sekmeden bir oyun başlatabilir ve eş kimliği kullanarak başka bir sekmeden (veya hatta WebRTC özellikli farklı bir web tarayıcısından) katılabilirsiniz.
Bazı hata ayıklama bilgilerini görmek için web tarayıcınızın konsolunu açabilirsiniz, çünkü bu örnek uygulamada PeerJS istemcisi ayrıntılı günlük kaydı gerçekleştirmek üzere yapılandırılmıştır.
Ama İşime Yaramıyor!
Bu oyunun bilgisayarınızda çalışmamasının iki ana nedeni vardır.
Henüz gerekli WebRTC API'lerini desteklemeyen bir web tarayıcısı kullanıyor olabilirsiniz. Bu durumda, WebRTC ve veri kanallarını destekleyen farklı bir tarayıcı denemek isteyebilirsiniz.
WebRTC destekli modern bir web tarayıcısı kullanıyorsanız, WebRTC'nin geçemeyeceği bir ağ altyapısının arkasında olma ihtimaliniz vardır. İdeal olarak bu sorun bir TURN sunucusuyla kolayca çözülebilir, ancak örnek uygulama bir tane kullanmadığından, hem siz hem de rakibiniz NAT'ların arkasındayken çalışmayacaktır.
Çözüm
WebRTC yeni bir teknolojidir ve uygulamaları olgunlaşmaktan oldukça uzaktır. Bunlar genellikle geliştiriciler için bazı benzersiz zorluklara neden olur. Bununla birlikte, kaba ham API'leri düzgün bir şekilde soyutlayan PeerJS gibi kitaplıkların mevcudiyeti ile, teknoloji zaten oldukça erişilebilir hale geliyor.
PeerJS tabanlı bir oyun oluşturmaya yönelik bu kısa öğreticinin, WebRTC ile başlamanıza ve bazı harika gerçek zamanlı eşler arası web uygulamaları oluşturmanıza yardımcı olacağını umuyorum.