Nastavenie multiplayerovej hry so Socket.io | hyperPad Documentation

Loading...

Logo

z-f2VkDQ.jpg

Časť 1: Úvod

Preferované predpoklady

V tomto návode sa zameriame na to, ako nastaviť server a pripojiť k nemu vašu hru, aby ste mohli povoliť funkcie pre viacerých hráčov pre váš projekt pomocou Socket.io správania. Budeme sa zaoberať pokročilými funkciami a správaním v hyperPad a silne odporúčame preštudovať niektoré ďalšie návody pred pokračovaním.

Tento návod predpokladá, že máte dobré porozumenie základným funkciám hyperPad ako aj minimálne znalosti písaného programovania, keďže sa budeme zameriavať na Javascript skripting na vytvorenie herného servera. Tento návod tiež predpokladá základné porozumenie sieťovaniu a rozdielom medzi serverom a jeho klientmi.

Primárnym cieľom tohto návodu je naučiť vás, čo musíte urobiť na pridanie funkčnosti pre viacerých hráčov do vašej hry; nie na vytvorenie samotnej hry. Preskúmame vzťah medzi Socket.io klientmi a serverom a ako spolu komunikujú pomocou Socket.io správania.

Požiadavky

Aby ste mohli vytvoriť a hostiť server, potrebujete počítač, ktorý dokáže spustiť Node.JS (Mac, Windows atď.). Inštalácia Node.JS a nastavenie pre naše účely budú pokryté v tomto návode. Ak hostíte server vo svojej domácej sieti, pravdepodobne budete musieť zmeniť nastavenia port-forwarding vášho brány, ak chcete mať prichádzajúce pripojenia z vonkajšej siete.

Pre tento návod sme už vytvorili jednoduchú ukážkovú hru. V nej hrajú dvaja hráči hru na označenie v malom bludisku. Preskúmame, ako sú použité Socket.io správania v ukážkovom projekte, takže je odporúčané stiahnuť a otvoriť projekt v hyperPad.

Skončený hyperPad ukážkový projekt si môžete stiahnuť tu: Multiplayer tag tutorial.tap

Prehľad

V tomto návode prejdeme základmi vytvorenia servera pre vašu hru. Server bude spravovať väčšinu detailov v hre, ako sú skóre, herné lobby atď. Potom vytvoríme správania, ktoré posielajú informácie z našej hry na server a naopak.

Toto je všeobecný tok našej hry:

1. Z hlavného menu sa pripojíme na náš server a necháme používateľa rozhodnúť sa, či chce vytvoriť alebo sa pripojiť k hre.

a. Ak vytvárate hru, načítajte čakáreň.

b. Ak sa pripájate k hre, načítajte zoznam dostupných herných miestností.

c. Keď sú dvaja hráči v čakárni, hra sa spustí.

2. V hre server náhodne umiestni hráčov do jednej zo štyroch oblastí a priradí jedného z nich ako „Toto“.

a. Označovanie iného hráča náhodne zmení ich polohy, zmení stav „Toto“ a pridá bod hráčovi, ktorý označil iného.

b. Ak sa počas určitého časového intervalu nenastanú žiadne označenia, server odníma 1 bod hráčovi, ktorý aktuálne je „Toto“ a zmení stav „Toto“ a predtým náhodne umiestni hráčov do spawn zón znova.

3. Akonáhle hráč dosiahne určitý počet bodov, načíta sa prekrytie vyhlasujúce víťaza. Potom sa hráči odpoja z miestnosti a vrátia do hlavného menu.

Časť 2: Nastavenie servera

Vytvorenie Socket.io servera si vyžaduje spustenie Javascript aplikácie pomocou Socket.io knižnice, ktorá čaká na pripojenia hráčov. Socket.io je Javascript sieťová knižnica, ktorá nám zjednodušuje veľa podrobností pri budovaní sieťovej aplikácie. Ďalšie podrobnosti nasledujú.

Stiahnutie a inštalácia Node.JS

Ak chcete začať, prejdite na Node.JS a stiahnite si ho do počítača (Mac, Windows atď.), na ktorom plánujete hostiť server. Po dokončení sťahovania spustite inštalačný program a riaďte sa jeho pokynmi. Všetky možnosti počas inštalácie môžete nechať ako predvolené. Node.JS nám umožňuje spúšťať Javascript aplikácie samostatne bez potreby webového prehliadača.

Stiahnutie a spustenie príkladového servera

Ďalej stiahnite Multiplayer Server Example tohto tutoriálu na GitHub:

https://github.com/hyperPad/multiplayerServerExample

Kliknite na tlačidlo "Clone or download" a vyberte "Download ZIP". Týmto sa stiahne kópia kódu pre príklad servera.

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

Rozbaľte stiahnutý ZIP. Vo vnútri nájdete niekoľko malých súborov, ale najvýznamnejším súborom je súbor "index.js", ktorý obsahuje kód pre náš server. Teraz otvorte príkazový riadok/terminál v priečinku príkladového servera.

Zadajte "npm install" a stlačte enter, a potom nechajte, aby to bežalo. npm je správa balíkov, ktorá číta súbor package.json a sťahuje potrebné balíky pre náš server. (Vrátane Socket.io!)

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

Keď príkaz skončí, máme všetko, čo potrebujeme na spustenie servera. V termináli zadajte "node ." a server sa spustí.

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

To je všetko! Náš server teraz čaká na prichádzajúce Socket.io pripojenia na porte 3000.

"node ." spúšťa Node.JS pre aktuálny adresár, kde hľadá indexový súbor adresára a spúšťa ho. Predvolene je to Javascript súbor "index.js", v ktorom sa nachádza väčšina kódu nášho servera a bude podrobne analyzovaný v priebehu tohto tutoriálu.

Nezabudnite nechať otvorený terminál, pretože jeho zatvorenie tiež uzavrie server. Uvidíte, ako sa objavia správy, keď sa hráči pripoja alebo odpoja, a keď sa miestnosti vytvárajú alebo ničia, ako aj iné udalosti.

Poznámka: Na povolenie prichádzajúcich pripojení z vonkajšej siete budete pravdepodobne musieť otvoriť port 3000 na vašej domácej bráne. Tento proces sa líši od siete k sieti, ale sprievodca sa zvyčajne dá nájsť hľadaním sprievodcu pre port-forwarding pre váš doma modem/router. Môžete byť potrební uzavrieť a reštartovať Node.JS server, keď zmeníte nastavenia port-forwarding.

Časť 3: Pripojenie k serveru

Akonáhle máte základy servera nastavené, môžeme sa teraz pripojiť k nemu v hyperPad hre. Toto by sa malo nastaviť, aby to bolo prvé, čo sa stane vo vašom projekte, bez ohľadu na to, na akej scéne sa nachádzate (keďže všetko musí komunikovať so serverom). Najlepšie je pripojiť toto správanie k objektu na Globálnej vrstve, takže sa bude uplatňovať vo všetkých scénach.

Untitled.jpg

V príklade projektu označenie Globálnej vrstvy "Server" obsahuje vyššie uvedené. (Stiahnutie projektu sa nachádza v časti 1 tohto návodu v sekcii Požiadavky.)

Tieto dve správania sú skutočne všetko, čo potrebujete na pripojenie k serveru. Najprv, pod vlastným záložkou, uchopte Socket.io Klient správanie a hodte ho dolu. Tu zadáte URL vášho servera pod záložkou URL v okne vlastností. Na hore uvedenom obrázku bola URL nášho servera na "http://192.168.0.191:3000", vrátane protokolu a portu. Chcete to zmeniť, aby sa zhodovalo s URL vášho servera, inak to pravdepodobne nebude fungovať, keď spustíte hru.

Teraz máme informácie o serveri, ktoré chceme, ale stále sa musíme k nemu pripojiť. Takže potrebujeme len Správanie pripojiť k Socket. Hodte jedno dolu, otvorte jeho vlastnosti a vyberte klienta v prázdnej krabičke a nastavte vlastnosť Funkcia na "Pripojiť".

Teraz, keď sa náš projekt načíta, automaticky sa pripojíme k našemu serveru.

mceclip1.png

Časť 4: Vytváranie a pripojovanie miestností

Ďalším krokom je vytvorenie našich herných lobby, kde sa môžu hráči pripojiť a hrať spolu.

mceclip2.png

Toto je naša jednoduchá obrazovka Hlavného menu. Všetko, čo musíte urobiť, je tapsnúť na jedno z tlačidiel, aby ste buď začali miestnosť, alebo hľadali dostupné miestnosti.

Vytváranie miestností

Poďme si skontrolovať, ako komunikovať so serverom, aby sme vytvorili našu miestnosť.

mceclip3.png

Celkom jednoduché, však? Aby sme to rýchlo prešli, akonáhle sa dotkneme nášho tlačidla, bude nás vyzvané, aby sme zadali názov miestnosti. Po vykonaní sa tohto názvu vysiela na server, kde sa miestnosť vytvára a načítame scénu čakárne.

Odtiaľto budeme často používať Emit na Socket. To je preto, že je našou hlavnou cestou na odosielanie údajov na server. Myslite na to jednoducho ako na "online verziu" Broadcast Message a Receive Message (Emit to Socket vykonáva obidve akcie naraz).

Teraz musíme pridať nejaké informácie na náš server, aby vytvoril miestnosť, keď obdrží správu z našich Emit správaní.

mceclip4.png

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

Táto línia vytvára socket udalosť (ako lambda výraz) na serveri, ktorá čaká na Emits so udalosťou 'createRoom'.

Prvý parameter je hodnota, ktorú prechádzame cez Emit na Socket správanie, v tomto prípade názov miestnosti, ktorý užívateľ zadal. Tu sme pomenovali tento parameter 'roomName'.

Druhý parameter je funkcia, ktorú zavoláme neskôr v socket udalosti, aby sme signalizovali klientovi. Emit na Socket správanie bude pokračovať v vykonávaní len vtedy, ak je zavolaná funkcia spätného volania na serveri. Tu sme pomenovali tento parameter 'callback'.

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

Toto vytvorí inštanciu štruktúry, ktorá bude obsahovať základné informácie o miestnosti.

'id' bude jedinečný identifikátor generovaný pomocou utilitárnej funkcie 'uuid()'. To nám pomôže špecificky identifikovať túto miestnosť oproti zoznamu mnohých ďalších vytvorených miestností neskôr.

'name' bude nastavené na názov, ktorý užívateľ zadal skôr.

'sockets' bude inicializované ako prázdne pole. Neskôr toto pole bude sledovať hráčské sockets pripojené k tejto miestnosti.

rooms[room.id] = room;

'rooms' je globálny zoznam miestností, ktoré sú aktuálne aktívne. Keďže vytvárame novú miestnosť, uložíme ju do zoznamu podľa jej ID.

joinRoom(socket, room);

Toto zavolá globálnu funkciu 'joinRoom' (riadok 29), ktorá pridá hráčske socket do poľa 'sockets' miestnosti. Keďže hráč vytvoril miestnosť, to tiež znamená, že sa do nej pripojí tiež.

callback();
});

Na konci zavoláme funkciu spätného volania, aby klient bol informovaný o tom, že miestnosť bola vytvorená. To umožní Emit na Socket pokračovať vo vykonávaní, čo načíta scénu čakárne nasledujúce. Toto tiež označuje koniec socket udalosti 'createRoom'.

Pripojenie k miestnostiam

Pripojenie k miestnostiam je trochu iné, pretože sa musíme dostať k informáciám z inej scény z tlačidla.

mceclip5.png

Pre pripojenie k miestnostiam sme umiestnili začiatok našich správaní na našu globálnu vrstvu spolu s tým, kde sa pripájame k serveru. Týmto spôsobom môžeme pristupovať k informáciám z ktorejkoľvek našich scén, v tomto prípade zoznamu miestností. Pre tlačidlo, dotknutie sa ho jednoducho načíta hráča do scény zoznamu miestností.

Tu máme naše druhé správanie pre komunikáciu so serverom. Socket Event si môžete myslieť ako Receive Message, pretože sa aktivuje len raz, keď je z servera vyslaná nastavená správa.

Najlepší spôsob, ako si myslieť pri použití Socket Event a Emit na Socket, je, že Socket Event reaguje len na informácie prichádzajúce zo servera, zatiaľ čo Emit na Socket je volaný v reakcii na miestne akcie.

Pok pokiaľ ide o našu logiku, akonáhle sa pripojíme k serveru, vyšleme žiadosť 'getRoomNames', aby sme dostali akékoľvek dostupné názvy miestností.

mceclip19.png

Potom nastavíme označenie, na ktoré môže hráč ťuknúť, aby sa dostal dnu.

mceclip6.png

Toto je naša scéna Zoznam miestností. Tu sa načítajú a zobrazia akékoľvek dostupné herné miestnosti. Jednoduchým ťuknutím na názov miestnosti sa hráč dostane dnu. Vďaka našim predchádzajúcim správam sa zoznam automaticky načíta akékoľvek otvorené miestnosti a spawne názvy miestností na obrazovke. Ak sa nič nezobrazuje, máme naše tlačidlo Obnoviť zoznam, ktoré jednoducho opakuje správanie na znovu načítanie.

mceclip7.png mceclip8.png

Tu máme logiku na nastavenie zoznamu. Nebudeme sa do detailov púšťať, pretože chceme len vedieť, ako to súvisí s naším serverom.

Na začiatku máme našu Emit na Socket správu. Táto žiada server, aby poslal informácie o dostupných miestnostiach. Odtiaľ máme získanie hodnoty z poľa. Všetky údaje, ktoré prichádzajú zo servera, budú odoslané ako pole a informácie, ktoré potrebujeme, budú na prvých hodnotách. Takže nastavujeme naše Získať pole hodnotu, aby získalo hodnotu na indexe 0. Odtiaľ naše správanie extrahujú tieto údaje a vytvorí sa štítok pre každú miestnosť, ktorá sa na našej obrazovke zobrazuje.

Ďalej skontrolujeme objekt, na ktorý sa potrebujeme dotknúť, v našej scéne je to štítok s označením Názov miestnosti.

mceclip9.png

Táto textová správa slúži ako naše tlačidlo pri spawne, ale ešte potrebujeme pripojiť ID miestnosti, s ktorou sa chceme pripojiť. Aby sme to urobili, najprv musíme uchopiť ID miestnosti, a to urobíme pomocou Získať atribút správanie a nastavíme to na dynamické. Potom vyšleme na server, že sa chceme pripojiť k tejto miestnosti a načítať sa do čakárne.

mceclip10.png

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

Toto je vstupný bod pre socket udalosť 'joinRoom'. Prvý parameter je hodnota, ktorú chceme získať, teda ID miestnosti, s ktorou sa chceme pripojiť, a to bolo odoslané na server. Tu sme pomenovali parameter 'roomId'.

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

Pomocou roomId, ktoré poskytuje klient, môžeme nájsť správnu inštanciu miestnosti na serveri. S týmto zavoláme globálnu funkciu 'joinRoom' (riadok 29) s socketom hráča, ktorý sa chce pripojiť a inštanciou miestnosti. Pozrieme sa na funkciu 'joinRoom' za chvíľu.

callback();
});

Na konci zavoláme funkciu spätného volania, aby sme oznámili klientovi, aby pokračoval v načítaní scény čakárne, čím označujeme koniec socket udalosti 'joinRoom'.

Takže, čo presne sa deje vo funkcii 'joinRoom'? Pozrime sa na to.

mceclip11.png

room.socket.push(socket);

Ako sme spomenuli skôr, pole 'room.socket' sleduje sockets, ktoré sú pripojené v miestnosti. Táto línia to presne robí tým, že pridá socket do poľa.

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

Toto je oficiálne volanie na pripojenie klienta k miestnosti. Najprv hovoríme socketu, aby pripojil miestnosť podľa jej ID. Keď je to dokončené, nasledujúca funkcia sa spustí, kde pripojíme ID miestnosti k socketu. Napokon, zapisujeme do konzoly, že hráč sa pripojil k miestnosti!

mceclip12.png

Čakáreň

Čakáreň je jednoducho scéna, do ktorej načítame hráčov, zatiaľ čo čakajú, až sa pripoja iní hráči alebo kým sa začína hra.

mceclip13.png

Po vstupe do miestnosti vyšleme serveru správu 'ready'. Akonáhle server obdrží dve z týchto správ, odosiela správu, že sa hra začína ('initGame'). Túto správu zachytíme pomocou našich Socket Event a teda načítame našu úroveň hry. Pre naše správanie to bude všetko. Môžete pridať tlačidlo, ktoré vás odpojí z miestnosti a pošle vás späť na hlavnú obrazovku, ak chcete.

Na serverovej strane sa pozrime na kód, aby sme zistili, čo sa tam deje.

mceclip14.png

Toto je udalosť 'ready', ktorá sa volá, keď sa klient pripojí do miestnosti a je pripravený na pripojenie.

const room = rooms[socket.roomId];

Keďže sme pripojili ID miestnosti k socketu, môžeme získať miestnosť, aby sme skontrolovali, či je hra schopná začať.

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

Tu kontrolujeme, či sú vo svojej miestnosti už dvaja hráči. Povedzme, že to je pravda, a pokračujeme v spustení hry.

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

Teraz, keď sú dvaja hráči, iterujeme cez každý socket a vysielame udalosť 'initGame', aby každý klient načítal scénu úrovne, ako sme to už spomenuli.

Časť 5: Hrateľnosť

Teraz sa dostávame k podstatným veciam. Toto je úroveň hry, ktorú sme navrhli pre tento návod.

mceclip15.png

Predtým, než sa do toho pustíme, máme štítok s názvom "Herná logika", poďme sa na to pozrieť.

mceclip16.png

Wow, to je veľa správaní! Nebojte sa, to je len to, ako spawujeme našich hráčov do hry. Pozrime sa bližšie;

mceclip17.png

Začínáme Emit na Socket správou, ktorá oznámia serveru, že sa naša hra začala, s udalosťou 'startGame'. Potom uchopíme pole, ktoré server vracia, vezmeme jeho prvú hodnotu a so Získať hodnotu z dictionary, zoberieme rôzne atribúty, ktoré náš objekt bude potrebovať. Samostatný strom robí to isté, s výnimkou toho, že pre protivníka. Napokon, vysielame správu 'init' našemu hráčskemu objektu, aby sme veci rozbehli.

Pozrime sa, čo sa deje na strane servera, keď vysielame udalosť 'startGame'.

mceclip20.png

Prvá polovica tejto socket udalosti, ktorú tu vidíte, nastavuje úvodné hodnoty na každého klienta a následne pridáva akéhokoľvek klienta, ktorý nie je emitovaným klientom, do miestneho poľa 'others'.

mceclip21.png

V druhej polovici sa vytvorí miestny zoznam 'ack', ktorý obsahuje informácie o nás a ostatných klientoch. Potom tieto informácie posielame späť klientovi odovzdaním našej dictionary 'ack' do funkcie spätného volania, ktorá sa stáva výslednou hodnotou vyžadovanej Emit na Socket správania.

Potom sa spustí časový úsek 5 sekúnd pred konečným začatím kola, pretože všetci majú všetky informácie, ktoré potrebujú na hranie hry. Funkcia 'beginRound' (riadok 99) riadi niektoré herne špecifické logiky pre tento projekt. Nechceme sa venovať podrobnostiam, ale v podstate sa tu upravuje, kde sa majú spawovať hráči, kontrolovať skóre a tiež informovať klientov, kto je „Toto“.

Ako sme už spomenuli, správa 'init' sa zavolá na našom štítku "Herná logika", keď je všetko pripravené. Teraz sa pozrieme na správanie na hráčskom objekte, ktoré prijíma správu 'init'.

mceclip22.png

Tu vidíte, že máme niekoľko stromov správania na našom hráčovi. Najprv sa začneme z horného ľavého stromu.

mceclip23.png

Toto je správanie, ktoré prakticky spúšťa všetko ostatné v našej hre.

Najprv prijmeme správu 'init', odoslanú z štítku "Herná logika". Odtiaľ uchopíme server ID nášho objektu a zapneme jedno z našich Socket Events a nastavíme hernú obrazovku tak, aby sme mohli presne sledovať našu postavu.

Synchronizácia pohybu

mceclip24.png

Tu je jedno z našich najdôležitejších správaní. Tento malý strom je navrhnutý na aktualizáciu pozície nášho hráča na serveri zakaždým, keď posunieme joystick. Určite ste si si všimli, že tiež odkazujeme na niektoré hodnoty dictionary. Tieto hodnoty získavame z samostatného správania dictionary, ktoré obsahuje X a Y pozície našich hráčov.

Pozrime sa na udalosť 'moved' na serveri.

mceclip25.png

data = JSON.parse(data);

Dictionaries, keď sú odoslané z klienta na server, musia byť analyzované, aby sa dal ľahko čítať. To je z dôvodu, že dictionaries v hyperPad sú zakódované do JSON štruktúry keď sa odosielajú na server. Táto línia analyzuje JSON reťazcovú štruktúru a uloží zoznam dictionary späť do rovnakej lokálnej premennej 'data'.

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

Tu aktualizujeme pozície X a Y uložené na socket s novými hodnotami, ktoré poskytol klient.

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
});
}

Ďalej iterujeme cez všetkých klientov, aby sme ich informovali o našich nových pozíciách a iných detailoch, okrem seba (t.j. Emitovaný klient nepotrebuje vedieť svoju vlastnú pozíciu).

mceclip26.png

Tento strom tu riadi väčšinu našej hry. Používame Socket Event, keď server kontroluje, ktorý hráč je označovaný ako Toto, čo je emitované 'beginRound' (riadok 99) na serveri.

Potom uchopíme ID nášho objektu zo seznamu a použijeme Dictionary Value na rozčlenenie rôznych častí údajov, ktoré obsahuje. Odtiaľ uchopíme naše Skóre, či sme označení ako "Toto", ako aj x a y pozície nášho objektu, potom ich priraďujeme atribútom objektu. Zvyšok správania je pre nastavenie a kontrolu UI v našej hre.

Záver

Tu bolo veľa informácií, ale dúfame, že ak ste sa dostali tak ďaleko, mali by ste mať predstavu o tom, ako využiť Socket.io správania na vytvorenie zážitkov pre viacerých hráčov pre vašich hráčov.

Vyskúšajte to sami! Vezmite si existujúcu hru, ktorú ste vytvorili, a pokúste sa jej dať nejakú online funkcionalitu, ako je scéna s tabuľkou najvyšších skóre, ktorá sa pripojí k serveru a požiada o zoznam najvyšších 10 skóre s menami hráčov na zobrazenie.

Je ťažké naučiť sa skriptovací jazyk, ako je Javascript, v jednom článku. Našťastie, ak máte nejaké problémy, existuje veľa iných zdrojov, ktoré vám pomôžu s písaním Javascript aplikácií pre Node.JS a Socket.io;

Naučte sa Javascript - https://developer.mozilla.org/bm/docs/Web/JavaScript

Naučte sa Socket.io - https://socket.io/docs/

Naučte sa Node.JS - https://nodejs.org/en/docs/