Menjinakkan WebRTC dengan PeerJS: Membuat Game Web P2P Sederhana
Diterbitkan: 2022-03-11WebRTC adalah teknologi yang memungkinkan komunikasi real-time antara browser web. Ini relatif baru, dan definisi API masih dianggap sebagai konsep. Ditambah dengan fakta bahwa WebRTC belum didukung oleh semua browser web utama, (dan di antara yang mendukung, beberapa di antaranya tidak mendukung setiap fitur teknologi ini), ini membuat penggunaan WebRTC relatif sulit untuk aplikasi penting apa pun. . Atau begitulah menurut Anda!
Sejak pertama kali diperkenalkan oleh Google pada Mei 2011, WebRTC telah digunakan di banyak aplikasi web modern. Menjadi fitur inti dari banyak browser web modern, aplikasi web dapat dengan mulus memanfaatkan teknologi ini untuk memberikan pengalaman pengguna yang lebih baik dalam banyak cara. Aplikasi streaming video atau konferensi yang tidak memerlukan plugin browser yang membengkak, dan dapat memanfaatkan jaringan peer-to-peer (P2P) (sambil tidak mentransmisikan setiap bit data melalui beberapa server) hanyalah bagian dari semua hal menakjubkan yang dapat dicapai dengan WebRTC.
Pada artikel ini, kita akan melihat bagaimana WebRTC dapat digunakan untuk membuat game web P2P sederhana dari Connect Four. Untuk mengatasi berbagai sisi kasar dan perbedaan implementasi WebRTC, kami akan menggunakan pustaka JavaScript yang luar biasa: PeerJS.
Data melalui WebRTC
Sebelum kita mulai, penting untuk dipahami bahwa WebRTC bukan hanya tentang transmisi aliran audio dan video. Ini juga menyediakan dukungan untuk saluran data P2P. Saluran ini datang dalam dua variasi: dapat diandalkan dan tidak dapat diandalkan. Seperti yang bisa diduga, saluran data yang andal menjamin bahwa pesan terkirim dan dikirimkan secara berurutan, sementara saluran yang tidak dapat diandalkan tidak memberikan jaminan seperti itu.
Selain itu, saluran data WebRTC tidak memerlukan pengaturan infrastruktur khusus, selain yang dibutuhkan oleh koneksi rekan WebRTC biasa: server pensinyalan untuk mengoordinasikan koneksi antar rekan, server STUN untuk mengetahui identitas publik rekan, dan opsional server TURN untuk merutekan pesan antar rekan jika koneksi langsung antar rekan tidak dapat dibuat (misalnya ketika kedua rekan berada di belakang NAT). Jika akronim ini terdengar familier, itu karena WebRTC menggunakan kembali teknologi yang ada jika memungkinkan.
Ini membuka pintu untuk lebih banyak kasus penggunaan WebRTC, termasuk tetapi tidak terbatas pada game multipemain, pengiriman konten, dan berbagi file. Sekali lagi, semua tanpa memerlukan server perantara apa pun dan karenanya dengan latensi yang lebih rendah.
Dalam permainan web sederhana kami, kami akan menggunakan saluran data antara dua browser web untuk mengomunikasikan gerakan pemain bolak-balik.
Temui PeerJS
PeerJS mengambil implementasi WebRTC di browser Anda dan membungkus API yang sederhana, konsisten, dan elegan di sekitarnya. Ini menyumbat berbagai lubang dalam implementasi WebRTC dari browser sebelumnya. Misalnya, di Chrome 30 atau lebih lama, hanya saluran data yang tidak dapat diandalkan yang tersedia. PeerJS, jika dikonfigurasi untuk menggunakan saluran data yang andal, akan menggunakan shim untuk browser lama tersebut. Meskipun ini tidak akan seperforma implementasi asli dari saluran yang andal, itu akan tetap berfungsi.
Dengan PeerJS, mengidentifikasi rekan bahkan lebih sederhana. Setiap rekan diidentifikasi hanya menggunakan ID. Sebuah string yang peer dapat memilih sendiri, atau memiliki server menghasilkan satu. Meskipun WebRTC menjanjikan komunikasi peer-to-peer, Anda tetap memerlukan server untuk bertindak sebagai perantara koneksi dan menangani pensinyalan. PeerJS menyediakan implementasi open source dari server broker koneksi ini PeerJS Server (ditulis dalam Node.js), jika Anda tidak ingin menggunakan versi cloud-host mereka (yang gratis saat ini, dan dilengkapi dengan beberapa batasan).
Hubungkan Empat Goes P2P
Sekarang kita memiliki sumber kepercayaan untuk bekerja dengan WebRTC, yaitu PeerJS, mari kita mulai dengan membuat aplikasi Node.js/Express sederhana.
npm init npm install express --save npm install jade --save npm install peer --save
Kami akan menggunakan ini hanya untuk meng-host Server PeerJS, dan menyajikan halaman dan aset front-end. Kita hanya perlu menyajikan satu halaman, dan ini akan berisi dua bagian: menu utama biasa, dan grid Connect Four 7-kali-6.
Server PeerJS
Hosting Server PeerJS kami sendiri sangat mudah. Repositori resmi di GitHub bahkan memiliki tombol sekali klik untuk menyebarkan instance PeerJS Server ke Heroku.
Dalam kasus kami, kami hanya ingin membuat instance ExpressPeerServer di aplikasi Node.js kami, dan menyajikannya di “/peerjs”:
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 }))
Klien PeerJS
Dengan PeerJS Server aktif dan berjalan, kami beralih ke sisi klien. Seperti dibahas sebelumnya, PeerJS mengidentifikasi rekan-rekan dengan ID unik. ID ini dapat dihasilkan oleh PeerServer untuk setiap rekan secara otomatis, atau kita dapat memilih satu untuk setiap rekan saat membuat instance objek Peer .
var peer = new Peer(id, options)
Di sini, id dapat dihilangkan sama sekali jika kita ingin server membuatkannya untuk kita. Dalam kasus kami, itulah yang ingin kami lakukan. PeerServer akan memastikan bahwa ID yang diberikannya unik. Argumen kedua, options , biasanya berupa objek yang berisi kunci (kunci API, jika Anda menggunakan PeerServer yang dihosting di cloud, atau Host , port , path , dll jika Anda menghosting PeerServer sendiri).
var peer = new Peer({ host: location.hostname, port: location.port || (location.protocol === 'https:' ? 443 : 80), path: '/peerjs' })
Untuk membuat koneksi antara dua rekan PeerJS, salah satu rekan harus mengetahui ID rekan lainnya. Demi menjaga hal-hal sederhana, dalam penerapan Connect Four kami melalui WebRTC, kami akan meminta pemain yang memulai permainan untuk membagikan ID rekan dengan lawannya. Dengan ID rekan tujuan yang diketahui, panggilan sederhana ke peer.connect(destId) adalah semua yang kita perlukan:

var conn = peer.connect(destId)
Baik objek Peer dan objek DataConnection yang dikembalikan oleh peer.connect(destId) memancarkan beberapa peristiwa yang sangat berguna yang layak untuk didengarkan. Untuk keperluan tutorial ini, kami secara khusus tertarik tentang kejadian 'data' dari objek DataConnection dan kejadian 'kesalahan' dari kedua objek.
Untuk mengirim data ke ujung koneksi yang lain, cukup panggil conn.send(data) :
conn.send('hello')
Meskipun sedikit berlebihan untuk kebutuhan kita di sini, PeerJS mentransmisikan data antar rekan setelah menyandikannya dalam format BinaryPack. Ini memungkinkan rekan-rekan untuk mengomunikasikan string, angka, array, objek, dan bahkan gumpalan.
Untuk menerima data yang masuk, cukup dengarkan event 'data' di conn :
conn.on('data', function(data) { // data === 'hello' })
Dan itu cukup banyak yang kita butuhkan!
Logika Permainan
Pemain pertama, yang memulai permainan, ditunjukkan ID rekan yang dihasilkan oleh PeerJS yang dapat mereka bagikan dengan lawan mereka. Setelah lawan bergabung dengan permainan menggunakan ID rekan pemain pertama, pemain pertama diizinkan untuk bergerak.
Connect Four, sebagai permainan aturan dan mekanisme sederhana, hanya memiliki satu jenis gerakan: setiap pemain, pada gilirannya, harus memilih kolom dan memasukkan cakram ke dalamnya. Ini berarti bahwa semua peer perlu berkomunikasi adalah nomor kolom di mana pemain saat ini telah memilih untuk memasukkan disknya. Kami akan mengirimkan informasi ini sebagai array dengan dua elemen: string 'move', dan angka - 0- berdasarkan indeks kolom dari kiri.
Setiap kali pemain mengklik kolom:
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])
Setelah mengirimkan data gerakan ini ke lawan, kami memperbarui status game secara lokal. Ini termasuk menentukan apakah pemain saat ini menang, atau jika pertandingan berakhir seri.
Di sisi penerima data pemindahan ini:
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
Dan tentu saja, setelah ini kami memperbarui status permainan secara lokal, menentukan apakah lawan telah menang atau jika permainan berakhir seri.
Perhatikan bagaimana kita perlu melakukan pemeriksaan kewarasan pada data yang masuk. Ini penting karena dengan game berbasis WebRTC, kami tidak memiliki server perantara dan logika game berbasis server yang memvalidasi data pemindahan.
Agar cuplikan tetap sederhana, baris kode yang memperbarui UI telah dihilangkan. Anda dapat menemukan kode sumber lengkap untuk JavaScript sisi klien di sini.
Menghubungkan Semuanya
Untuk menggabungkan semuanya, kami membuat halaman sederhana dengan dua bagian. Pada pemuatan halaman, bagian yang berisi menu utama ditampilkan, bagian yang berisi kisi-kisi permainan disembunyikan.
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
Membuat elemen DOM ini terlihat cantik berada di luar cakupan tutorial ini. Oleh karena itu kami akan menggunakan Bootstrap pendamping tepercaya kami dan melakukan penataan ringan di atasnya.
Saat pemain pertama mengklik tombol “Start”, petak permainan terungkap bersama dengan ID rekan pemain. Pemain kemudian dapat membagikan ID rekan ini dengan lawan mereka.
Pemain kedua dapat mengklik lalu mengklik tombol “Gabung”, masukkan ID rekan pemain pertama, dan mulai permainan.
Mencobanya
Anda dapat mencoba aplikasi contoh ini di https://arteegee.herokuapp.com.
Atau, Anda dapat mengkloning repositori dari GitHub, menginstal dependensi NPM, dan mencobanya secara lokal:
git clone https://github.com/hjr265/arteegee.git cd arteegee npm install PORT=5000 npm start
Setelah server berjalan, Anda dapat mengarahkan browser web Anda ke http://localhost:5000, memulai permainan dari satu tab, dan bergabung dari tab lain (atau bahkan browser web berkemampuan WebRTC yang berbeda) menggunakan ID rekan.
Anda dapat membuka konsol browser web Anda untuk melihat beberapa informasi debug, seperti dalam contoh aplikasi ini, klien PeerJS telah dikonfigurasi untuk melakukan pencatatan verbose.
Tapi Itu Tidak Bekerja untuk Saya!
Ada dua alasan utama mengapa game ini mungkin tidak berfungsi di komputer Anda.
Mungkin Anda menggunakan browser web yang belum mendukung API WebRTC yang diperlukan. Jika demikian, Anda mungkin ingin mencoba peramban lain - peramban yang mendukung WebRTC dan saluran data.
Jika Anda menggunakan browser web modern dengan dukungan WebRTC, maka ada kemungkinan Anda berada di belakang beberapa infrastruktur jaringan yang tidak dapat ditembus oleh WebRTC. Idealnya masalah ini dapat dengan mudah diatasi dengan server MENGHIDUPKAN, tetapi karena aplikasi contoh tidak menggunakannya, itu tidak akan berfungsi ketika Anda dan lawan Anda berada di belakang NAT.
Kesimpulan
WebRTC adalah teknologi baru, dan implementasinya masih jauh dari matang. Ini sering menyebabkan beberapa tantangan unik bagi pengembang. Namun, dengan ketersediaan perpustakaan seperti PeerJS yang dengan rapi mengabstraksi API mentah yang kasar, teknologi ini sudah menjadi cukup mudah diakses.
Saya harap tutorial singkat untuk membangun game berbasis PeerJS ini akan membantu Anda memulai dengan WebRTC dan membangun beberapa aplikasi web peer-to-peer real-time yang menakjubkan.