Mengatur Permainan Multiplayer dengan Socket.io | hyperPad Documentation

Loading...

Logo

z-f2VkDQ.jpg

Bagian 1: Pendahuluan

Prasyarat yang Disarankan

Dalam tutorial ini, kami akan fokus pada cara menyiapkan server dan menghubungkan permainan Anda ke server tersebut agar Anda dapat mengaktifkan fungsi multiplayer untuk proyek Anda melalui perilaku Socket.io. Kami akan membahas fitur dan perilaku canggih di hyperPad dan sangat disarankan untuk meninjau beberapa tutorial lainnya terlebih dahulu dan memiliki pemahaman yang baik tentang perangkat lunak sebelum melanjutkan.

Tutorial ini mengasumsikan Anda memiliki pemahaman yang baik tentang fungsi dasar hyperPad serta pemahaman minimal tentang pemrograman tertulis, karena kami akan fokus pada skrip Javascript untuk membangun server permainan. Tutorial ini juga mengasumsikan pemahaman dasar tentang jaringan dan perbedaan antara server dan kliennya.

Tujuan utama dari tutorial ini adalah untuk mengajarkan Anda apa yang perlu Anda lakukan untuk menambahkan fungsi multiplayer ke dalam permainan Anda; bukan untuk membuat permainan itu sendiri. Kami akan menjelajahi hubungan antara klien Socket.io dan server, serta bagaimana mereka berkomunikasi satu sama lain dengan perilaku Socket.io.

Persyaratan

Untuk membuat dan menghosting server, Anda akan membutuhkan komputer yang mampu menjalankan Node.JS (Mac, Windows, dll). Instalasi Node.JS dan pengaturannya untuk tujuan kami akan dibahas dalam tutorial ini. Jika Anda menghosting server di jaringan rumah Anda, Anda mungkin perlu mengubah pengaturan port-forward gateway Anda jika Anda ingin memiliki koneksi masuk dari luar jaringan lokal Anda.

Untuk tutorial ini, kami telah membuat permainan demo sederhana. Di dalamnya, kami memiliki dua pemain yang bermain tag dalam maze kecil. Kami akan menjelajahi bagaimana perilaku Socket.io digunakan dalam proyek contoh, jadi disarankan Anda mengunduh dan membuka proyek tersebut di hyperPad.

Proyek contoh hyperPad yang sudah selesai dapat diunduh di sini: Multiplayer tag tutorial.tap

Tinjauan

Dalam tutorial ini, kami akan menjelaskan dasar-dasar membuat server untuk permainan Anda. Server akan menangani sebagian besar detail dalam permainan seperti pencetakan skor, ruang permainan, dll. Kemudian, kami akan membuat perilaku yang mengirimkan informasi dari permainan kami ke server dan sebaliknya.

Berikut adalah alur umum permainan kami:

1. Dari menu utama, kami akan terhubung ke server kami dan membiarkan pengguna memutuskan untuk membuat atau bergabung dengan permainan.

a. Jika membuat permainan, muat ruang tunggu.

b. Jika bergabung dengan permainan, muat daftar ruang permainan yang tersedia.

c. Ketika dua pemain berada di ruang tunggu, permainan diluncurkan.

2. Dalam permainan, server secara acak menempatkan pemain di salah satu dari empat area dan menetapkan salah satu dari mereka menjadi "It".

a. Men-tag pemain lain akan mengacak lokasi mereka, menukar status It dan menambah poin bagi pemain yang men-tag yang lainnya.

b. Jika tidak ada tag yang terjadi dalam waktu tertentu, server akan mengurangi 1 poin dari pemain yang saat ini menjadi It dan menukar status It sebelum secara acak menempatkan pemain di zona spawn sekali lagi.

3. Setelah seorang pemain mencapai jumlah poin tertentu, akan dimuat overlay yang menyatakan pemenang. Kemudian, pemain akan terputus dari ruang tersebut dan kembali ke menu utama.

Bagian 2: Mengatur Server

Membuat server Socket.io mengharuskan kami untuk menjalankan aplikasi Javascript menggunakan pustaka Socket.io, yang mendengarkan koneksi pemain. Socket.io adalah pustaka jaringan Javascript yang menyederhanakan banyak dari kerja internal untuk membangun aplikasi jaringan untuk kami. Detail lebih lanjut akan menyusul.

Unduh dan Instal Node.JS

Untuk memulai, kunjungi Node.JS dan unduh ke komputer (Mac, Windows, dll.) yang ingin Anda host server. Setelah selesai mengunduh, jalankan penginstal dan ikuti instruksinya. Semua opsi selama instalasi dapat dibiarkan default. Node.JS memberi kami kemampuan untuk menjalankan aplikasi Javascript secara mandiri tanpa memerlukan browser web.

Unduh dan Jalankan Contoh Server

Selanjutnya, unduh Contoh Server Multiplayer tutorial ini di GitHub:

https://github.com/hyperPad/multiplayerServerExample

Klik tombol "Clone or download" dan pilih "Download ZIP". Ini akan mengunduh salinan kode untuk contoh server.

chrome_2019-08-05_14-22-14.png

Ekstrak ZIP yang diunduh. Di dalamnya Anda akan menemukan beberapa file kecil, tetapi file yang paling mencolok di sini adalah file "index.js" yang merupakan kode untuk server kami. Selanjutnya, buka command line/terminal Anda di dalam folder contoh server.

Ketik "npm install" dan tekan enter, lalu biarkan ia berjalan. npm adalah pengelola paket yang membaca file package.json dan mengunduh paket yang diperlukan untuk server kami. (Termasuk Socket.io!)

cmd_2019-08-05_14-55-19.png

Ketika perintah selesai, kami memiliki semua yang kami butuhkan untuk menjalankan server. Di terminal, ketik "node ." dan server akan dimulai.

cmd_2019-08-05_15-02-38.png

Selesai! Server kami sekarang mendengarkan pada port 3000 untuk koneksi Socket.io yang masuk.

"node ." meluncurkan Node.JS untuk direktori saat ini, di mana ia akan mencari file indeks direktori dan menjalankannya. Secara default, ini adalah file Javascript "index.js", yang merupakan lokasi sebagian besar kode server kami dan akan dianalisis di seluruh tutorial ini.

Biarkan terminal terbuka, karena menutupnya juga akan menutup server. Anda akan melihat pesan yang dicetak ketika pemain terhubung atau terputus, dan ketika ruang dibuat atau dihancurkan, dan acara lainnya.

Catatan: Untuk memungkinkan koneksi yang masuk dari luar jaringan rumah, Anda mungkin perlu membuka port 3000 di gateway rumah Anda. Proses ini bervariasi dari jaringan satu ke jaringan lainnya, tetapi panduan biasanya dapat ditemukan dengan melakukan pencarian internet untuk panduan port-forwarding untuk modem/router rumah Anda. Anda mungkin perlu menutup dan memulai ulang server Node.JS ketika Anda mengubah pengaturan port-forwarding.

Bagian 3: Menghubungkan ke Server

Setelah Anda memulai server dasar, kita sekarang dapat terhubung ke server tersebut dalam permainan hyperPad. Ini harus disiapkan untuk menjadi hal pertama yang terjadi di proyek Anda terlepas dari adegan mana yang Anda gunakan (karena semuanya perlu berkomunikasi dengan server). Sebaiknya lampirkan perilaku ini ke objek di Global Layer agar dapat diterapkan di semua adegan.

Untitled.jpg

Dalam proyek contoh, label Global Layer "Server" berisi di atas. (Unduhan untuk proyek dapat ditemukan di Bagian 1 tutorial ini di bawah bagian Persyaratan.)

Dua perilaku ini sebenarnya adalah semua yang Anda butuhkan untuk terhubung ke server. Pertama, di bawah tab kustom, ambil perilaku Klien Socket.io dan letakkan di bawah. Di sini, Anda akan memasukkan URL server Anda di bawah tab URL di jendela propertinya. Dalam gambar di atas, URL server kami berada di "http://192.168.0.191:3000", termasuk protokol dan port. Anda harus mengubah ini agar sesuai dengan URL server Anda atau kemungkinan besar tidak akan berfungsi ketika Anda memulai permainan.

Sekarang kami memiliki informasi server yang diinginkan, tetapi kami masih perlu terhubung ke server. Jadi, yang perlu kita lakukan adalah perilaku Hubungkan ke Socket. Letakkan satu di bawah, buka propertinya dan pilih klien di kotak kosong dan atur properti Fungsi ke "Connect".

Sekarang, ketika proyek kami dimuat, kami secara otomatis akan terhubung ke server kami.

mceclip1.png

Bagian 4: Membuat dan Bergabung dengan Ruang

Langkah selanjutnya adalah membuat ruang permainan kami di mana pemain dapat bergabung dan bermain bersama.

mceclip2.png

Berikut adalah layar Menu Utama kami yang sederhana. Yang perlu Anda lakukan adalah mengetuk salah satu tombol untuk memulai ruang atau mencari ruang yang tersedia.

Membuat Ruang

Mari kita periksa bagaimana kita berkomunikasi dengan server untuk membuat ruang kami.

mceclip3.png

Agak sederhana bukan? Jadi untuk meninjau ini dengan cepat, setelah kami menyentuh tombol kami akan diminta untuk mengetik nama ruang. Setelah itu selesai, nama tersebut dikirimkan ke server di mana ruang dibuat dan kami memuat adegan ruang tunggu.

Dari sini, kami akan sering menggunakan Emit ke Socket. Itu karena ini adalah cara utama kami untuk mengirim data ke server. Anggap saja itu sebagai "versi online" dari Siarkan Pesan dan Terima Pesan (Emit ke Socket melakukan kedua tindakan sekaligus).

Sekarang, kita perlu menambahkan beberapa informasi ke server kita sehingga server akan membuat ruang setelah menerima pesan dari perilaku Emit kami.

mceclip4.png

socket.on('createRoom', (roomName, callback) => {

Baris ini membuat acara soket (sebagai ekspresi lambda) di server, mendengarkan Emits dengan acara 'createRoom'.

Parameter pertama adalah nilai yang kami kirimkan melalui perilaku Emit ke Socket, dalam hal ini nama ruang yang diketik pengguna. Di sini, kami menamai parameter tersebut 'roomName'.

Parameter kedua adalah fungsi yang kami panggil kemudian dalam acara soket untuk memberi sinyal kepada klien. Perilaku Emit ke Socket hanya akan melanjutkan eksekusi jika fungsi callback dipanggil di server. Di sini, kami menamai parameter tersebut 'callback'.

const room = {
id: uuid(),
name: roomName,
sockets: []
};

Ini akan membuat suatu struktur yang akan menyimpan informasi penting tentang ruang tersebut.

'id' akan menjadi pengenal unik yang dihasilkan oleh fungsi utilitas 'uuid()'. Ini akan membantu kami mengidentifikasikan secara spesifik ruang ini terhadap daftar ruang yang telah dibuat lainnya nanti.

'name' akan diatur dengan nama yang diketik pengguna sebelumnya.

'sockets' akan diinisialisasi sebagai array kosong. Nanti, ini akan melacak soket pemain yang terhubung ke ruang tersebut.

rooms[room.id] = room;

'rooms' adalah daftar global dari ruang yang saat ini aktif. Karena kami sedang membuat ruang baru, kami akan menyimpannya di daftar berdasarkan ID-nya.

joinRoom(socket, room);

Ini akan memanggil fungsi global 'joinRoom' (baris 29), yang akan menambahkan soket pemain ke array 'sockets' ruang tersebut. Karena pemain yang membuat ruang, ini juga akan membuat mereka bergabung, juga.

callback();
});

Terakhir, kami memanggil fungsi callback sehingga klien diberitahu bahwa ruang telah dibuat. Ini akan memungkinkan Emit ke Socket untuk melanjutkan eksekusi, yang akan memuat adegan Ruang Tunggu selanjutnya. Ini juga menandai akhir dari acara soket 'createRoom'.

Bergabung dengan Ruang

Bergabung dengan ruang sedikit berbeda karena kami perlu mengakses informasi dari adegan yang berbeda dari tombol tersebut.

mceclip5.png

Untuk bergabung dengan ruang, kami telah menempatkan awal perilaku kami di lapisan global bersamaan dengan di mana kami terhubung ke server. Cara ini kami bisa mengakses informasi dari adegan mana pun, dalam hal ini daftar ruang kami. Untuk tombol, menekannya akan langsung memuat pemain ke adegan daftar ruang.

Di sini kami memiliki perilaku kedua untuk berkomunikasi dengan server. Acara Soket dapat dianggap seperti Terima Pesan karena hanya akan diaktifkan setelah pesan yang ditetapkan disiarkan dari server.

Cara terbaik untuk memikirkan saat menggunakan Acara Soket dan Emit ke Socket adalah bahwa Acara Soket bereaksi hanya terhadap informasi yang datang dari server, sementara Emit ke Socket dipanggil sebagai reaksi terhadap tindakan yang dilakukan secara lokal.

Mengenai logika kami, setelah kami terhubung ke server, kami akan Emit permintaan 'getRoomNames' untuk mendapatkan nama ruang yang tersedia.

mceclip19.png

Kemudian, kami akan menetapkan label yang dapat diketuk oleh pemain untuk masuk.

mceclip6.png

Ini adalah adegan Daftar Ruang kami. Di sini adalah tempat semua ruang permainan yang tersedia akan dimuat dan ditampilkan. Dengan hanya mengetuk nama ruang akan memuat pemain masuk. Berkat perilaku kami sebelumnya, daftar akan secara otomatis memuat ruang yang terbuka dan memunculkan label nama ruang di layar. Jika tidak ada apa-apa yang muncul, kami memiliki tombol Refresh List yang akan mengulangi perilaku untuk memuat mereka sekali lagi.

mceclip8.png

Di sini kami memiliki logika untuk mengatur daftar. Kami tidak akan terlalu banyak membahas di sini karena kami hanya ingin tahu bagaimana ini terhubung dengan server kami.

Untuk memulai, kami memiliki perilaku Emit ke Socket. Ini memanggil server untuk mengirim informasi tentang ruang yang tersedia. Dari sana, kami memiliki perilaku Ambil Nilai Array. Semua data yang berasal dari server akan dikirim sebagai Array dan informasi yang dibutuhkan akan berada pada nilai pertama. Jadi, kami mengatur Behaviors Genap Array untuk mendapatkan nilai di indeks 0. Dari sana, perilaku kami akan mengekstrak data itu dan membuat label untuk setiap ruang, menampilkannya di layar kami.

Selanjutnya, kami akan memeriksa objek yang perlu kami ketuk, di adegan kami ini adalah label yang disebut Nama Ruang.

mceclip9.png

Teks ini berfungsi sebagai tombol kami saat muncul, tetapi kami masih perlu melampirkan ID ruang yang ingin kami hubungkan. Untuk melakukan itu, kami terlebih dahulu perlu mendapatkan ID ruang, dan kami melakukannya dengan perilaku Dapatkan Atribut dan mengatur menjadi dinamis. Kemudian, kami Emit ke server bahwa kami ingin bergabung dengan ruang ini dan memuat ke ruang tunggu.

mceclip10.png

socket.on('joinRoom', (roomId, callback) => {

Ini adalah titik masuk untuk acara soket 'joinRoom'. Nilai parameter pertama adalah ID ruang yang ingin kami bergabung yang dikirimkan ke server. Di sini, kami menamai parameternya 'roomId'.

const room = rooms[roomId];
joinRoom(socket, room);

Dengan menggunakan roomId yang diberikan oleh klien, kami dapat menemukan instance ruang yang benar di server. Dengan itu, kami memanggil fungsi global 'joinRoom' (baris 29) dengan soket pemain yang ingin terhubung, dan instance ruang itu sendiri. Kami akan melihat fungsi 'joinRoom' sebentar lagi.

callback();
});

Terakhir, kami memanggil fungsi callback untuk memberi tahu klien untuk melanjutkan memuat adegan Ruang Tunggu, menandai akhir dari acara soket 'joinRoom'.

Jadi, apa yang sebenarnya terjadi di fungsi 'joinRoom'? Mari kita lihat.

mceclip11.png

room.socket.push(socket);

Seperti yang disebutkan sebelumnya, array anggota 'room.socket' melacak soket yang terhubung dalam sebuah ruang. Baris ini melakukan hal itu dengan mendorong soket ke dalam array.

socket.join(room.id, () => {
socket.roomId = room.id;
console.log(socket.id, "Bergabung", room.id);
});

Ini adalah panggilan resmi untuk menghubungkan klien ke sebuah ruang. Pertama kami memberi tahu soket untuk bergabung dengan sebuah ruang berdasarkan ID-nya. Ketika itu selesai, callback berikutnya dipanggil, di mana kami melampirkan ID ruang ke soket. Terakhir, kami mencatat di konsol bahwa seorang pemain telah bergabung dengan sebuah ruang!

mceclip12.png

Ruang Tunggu

Ruang tunggu adalah sekadar adegan yang kami muatkan ke pemain saat mereka menunggu pemain lain bergabung, atau untuk memulai permainan.

mceclip13.png

Dengan masuk ke ruang, kami akan emit pesan 'ready' ke server. Setelah server menerima dua dari ini, ia akan mengirim pesan bahwa permainan akan dimulai ('initGame'). Kami mengambil pesan itu dengan Acara Soket kami dan dengan demikian, memuat level permainan kami. Untuk perilaku kami, cukup itu saja. Anda dapat menambahkan tombol yang akan memutuskan Anda dari ruang dan mengembalikan Anda ke menu utama jika Anda mau.

Di sisi server, mari kita analisis kode untuk melihat apa yang terjadi di sana.

mceclip14.png

Ini adalah acara 'ready' yang dipanggil ketika klien telah bergabung dengan sebuah ruang dan siap untuk terhubung.

const room = rooms[socket.roomId];

Karena kami telah melampirkan ID ruang ke soket, kami dapat mengambil ruang tersebut untuk memeriksa apakah permainan dapat dimulai.

if (room.sockets.length == 2) {

Di sini kami memeriksa untuk melihat apakah sekarang ada dua pemain yang menunggu di ruang tersebut. Mari kita katakan bahwa itu sekarang benar, dan kami melanjutkan untuk memulai permainan.

for (const client of room.sockets) {
client.emit('initGame');
}

Sekarang setelah ada dua pemain, kami mengulangi setiap soket dan emit acara 'initGame' sehingga setiap klien memuat adegan Level, seperti yang ditunjukkan sebelumnya.

Bagian 5: Gameplay

Sekarang, untuk masuk ke bagian yang lebih dalam. Ini adalah di mana 90% dari pekerjaan kami akan dilakukan. Di bawah ini adalah level permainan yang kami desain untuk tutorial ini.

mceclip15.png

Sebelum kita melanjutkan, kami memiliki label bernama "Logika Permainan", mari kita buka dan lihat.

mceclip16.png

Wow, itu banyak perilaku! Jangan khawatir, ini hanya bagaimana kami memunculkan pemain kami ke dalam permainan. Mari kita lihat lebih dekat;

mceclip17.png

Kami mulai dengan perilaku Emit ke Socket yang memberi tahu server bahwa permainan kami telah dimulai, dengan acara 'startGame'. Kami kemudian mengambil array yang dikembalikan server, mengambil nilai pertamanya dan dengan Dapatkan Nilai Kamus, kami mengambil berbagai atribut yang akan dibutuhkan objek kami. Sebuah pohon terpisah melakukan hal yang sama, kecuali untuk pemain lawan. Akhirnya, kami menyiarkan pesan 'init' ke objek pemain kami untuk memulai semuanya.

Kita lihat sekarang apa yang terjadi di sisi server ketika kami emit acara 'startGame'.

mceclip20.png

Setengah pertama dari acara soket ini yang Anda lihat di sini adalah mengatur beberapa nilai awal pada setiap klien, kemudian menambahkan klien mana pun yang bukan klien yang emit ke dalam array 'others' lokal.

mceclip21.png

Di setengah kedua, sebuah daftar kamus lokal yang disebut 'ack' dibuat. Di dalamnya, kami memiliki informasi tentang diri kami, dan klien lain. Kami kemudian mengirimkan informasi itu kembali ke klien dengan meneruskan kamus 'ack' kami ke fungsi callback, yang menjadi nilai hasil dari Emit ke Socket yang dilepaskan.

Setelah itu, panggilan timeout selama 5 detik dibuat untuk akhirnya memulai ronde, sekarang setelah semuanya memiliki semua informasi yang mereka butuhkan untuk bermain. Fungsi 'beginRound' (baris 99) mengontrol beberapa logika permainan khusus untuk proyek ini. Kami tidak akan membahasnya terlalu dalam, tetapi pada dasarnya ini menangani di mana untuk memunculkan pemain, memeriksa skor, serta memberi tahu klien siapa yang menjadi It.

Seperti yang disebutkan sebelumnya, pesan 'init' dipanggil pada label "Logika Permainan" ketika semuanya siap. Di objek pemain, kami sekarang akan melihat perilaku di mana ia menerima pesan 'init'.

mceclip22.png

Di sini Anda dapat melihat bahwa kami memiliki beberapa pohon perilaku di pemain kami. Pertama, kami akan mulai dengan pohon di sudut kiri atas.

mceclip23.png

Ini adalah perilaku yang praktis memulai segalanya di permainan kami.

Pertama, kami menerima pesan 'init' yang dikirim dari label "Logika Permainan". Dari sana, kami mengambil ID server objek kami dan menghidupkan salah satu Acara Soket kami serta menyiapkan layar permainan kami sehingga kami dapat mengikuti karakter kami dengan akurat.

Penyelarasan Gerakan

mceclip24.png

Ini adalah salah satu perilaku terpenting kami. Pohon kecil ini dirancang untuk memperbarui posisi pemain kami di server setiap kali kami menggerakkan joystick. Anda mungkin telah memperhatikan bahwa ini juga mereferensikan beberapa nilai kamus. Kami mendapatkan nilai tersebut dari perilaku kamus mandiri yang berisi posisi X dan Y pemain kami.

Mari kita lihat acara 'moved' di server.

mceclip25.png

data = JSON.parse(data);

Kamus, ketika dikirim dari klien ke server, harus diurai agar data dapat dibaca dengan mudah. Ini karena kamus di hyperPad dikodekan ke dalam struktur JSON ketika dipancarkan ke server. Baris ini mengurai struktur string JSON dan menyimpan daftar kamus kembali ke dalam variabel 'data' lokal yang sama.

socket.x = data.x;
socket.y = data.y;

Di sini, kami memperbarui posisi X dan Y yang disimpan pada soket dengan nilai baru yang diberikan oleh klien.

for (const client of room.sockets) {
if (client == socket) {
continue;
}
client.emit(socket.id, {
x: socket.x,
y: socket.y,
score: socket.score,
isIt: socket.isIt
});
}

Selanjutnya, kami mengulangi semua klien untuk memperbarui mereka tentang posisi kami yang baru dan detail lainnya, dengan mengecualikan diri kami sendiri (misalnya, Klien yang mengemisi tidak perlu mengetahui posisi mereka sendiri).

mceclip26.png

Pohon ini mengontrol sebagian besar permainan kami. Kami menggunakan Acara Soket ketika server memeriksa pemain mana yang ditandai sebagai It, yang dipancarkan oleh 'beginRound' (baris 99) di server.

Kemudian, kami mengambil ID server objek kami dari array dan menggunakan Nilai Kamus untuk memecahkannya menjadi berbagai bagian data yang terkandung. Dari sana, kami mengambil Skor kami, apakah kami ditandai sebagai It, serta posisi x dan y objek kami kemudian menerapkannya pada atribut objek tersebut. Sisanya adalah untuk mengatur dan mengontrol UI dalam permainan kami.

Kesimpulan

Ada banyak hal yang harus dipahami di sini, tetapi berharap jika Anda sampai sejauh ini Anda harus memiliki pemahaman tentang cara memanfaatkan perilaku Socket.io untuk menciptakan pengalaman multiplayer bagi pemain Anda.

Cobalah sendiri! Ambil permainan yang sudah ada yang telah Anda buat dan coba berikan beberapa fungsi online, seperti adegan papan skor yang menghubungkan ke server dan meminta daftar 10 skor teratas dengan nama pemain untuk ditampilkan.

Sulit untuk mengajarkan bahasa skrip seperti Javascript dalam satu artikel. Untungnya, jika Anda mengalami masalah, ada banyak sumber daya lain untuk membantu Anda menulis aplikasi Javascript untuk Node.JS dan Socket.io;

Belajar Javascript - https://developer.mozilla.org/bm/docs/Web/JavaScript

Belajar Socket.io - https://socket.io/docs/

Belajar Node.JS - https://nodejs.org/en/docs/