Tutvustus

Näidete juures kasutame Kryonet teeki (library) ja Libgdx raamistikku (framework). Näited tulevad ühest eelmisel aastal tehtud projektist. Projektis on kohti, mida oleks saanud teha efektiivsemalt, nii et ei soovita midagi üks ühele maha teha.

Multiplayer mängude tegemisel on keskseks osaks info jagamine. Info jagamist saab realiseerida kõige lihtsamalt klient-server (client-server) mudeli abil, kuigi on ka teisi võimalusi, kuidas info jagamist realiseerida. Selle mudeli peamine idee seisneb selles, et mängu loogika - näiteks objekti liikumine x, y teljel - toimub serveris ja visuaalne pool toimub clientis. Selleks, et multiplayer mängu teha, tuleks kohe alguses hakata raliseerima projekti selle mudeli alusel, muidu hiljem läheb selle tegemine väga keeruliseks.

Mängu üheks põhikomponendiks on maailma mudel, mis hoiab mängu hetke seisu - state - ja mis on nii kliendis kui ka serveris. Selleks, et mulitplayer mäng ilusasti toimiks, peavad igal kliendil maailmamudelid ühtima. Kõige lihtsam on sellist asja realiseerida autoriteetse serveri abil. Mängu loogika toimub klient-server mudelis nii, et server hoiab endas siis nö “õiget” maailmamudelit, mida saadetakse klientitele, et nende maailmamudelid ühtiksid. Suurtemate projektide jaoks võib nii lihtsakoelisel lähenemisel probleeme tekkida, näiteks võib juhtuda selline olukord, kus saadetakse liiga palju informatsiooni liiga kiiresti serverisse ja tänu sellele võib võrk (network) olla ülekoormatud, mis tekitab mängus viivitusi (lag). Selle aine raames aga sellise probleemiga väga kokku õnneks ei puutu, kuna mängud on väiksemahulised. Kui probleem tekib, siis saab tõenäoliselt kuskil lihtsa optimeerimise teha, et probleem ära kaoks.

Javas on palju võimalusi, kuidas klienti ja serveri vahelist suhtlust realiseerida. Kõige lihtsam oleks seda teha Kryonet või Netty teekide abil - siinkohal vihje, et kui tekib arusaamatusi teekide toimimise kohta, siis vaadake nende dokumentatasioone ja tavaliselt on ka dokumentatsioonis tehtud lihtsamaid näiteid kuidas teeki kasutada. Siin on näiteks Kryoneti enda poolt tehtud näited. Samuti on ka Nettyl teegi kasutamise näited.

Klient-serveri mudeli toimimise loogika peaks olema teile tuttav ainest Arvutivõrkude alused (ICA0013), aga siiski kordaks siinkohal põhilised asjad üle. Põhimõtteliselt on klient ja server kahes eraldi arvutis, mis suhtlevad omavahel saates pakette (packet). Arvutid suhtlevad ip aadresside ja portide abil. Port võtab andmeid vastu teatud rakenduse/protsessi jaoks. Teie rakendusel läheb tavaliselt vaja kahte porti, üks TCP ja teine UDP saatmiseks. TCP on aeglasem aga kindlam protokoll, sellega on mõtekas saata näiteks tegelastega mängus tegelaste liikumist. UDP on kiirem aga ebakindlam, sellega on näiteks hea saata mõnes tulistamise mängus kuulide asukoht, kuna nende informatsioon peab kiirelt edasi-tagasi kliendi ja serveri vahel liikuma.

Etteantud pildil on näha Serveri poolse Serveri klassi tegemist, kus punasega on ära märgitud TCP ja UDP portide määramine nendele määratud arvude järgi. Näiteprojektis on fail siin.

Server class

Kliendi pool on pilt umbes sama, kuid on vaja ka määrata ip aadress, kuhu packeteid saadetakse. Siin on näidatud kuidas kliendi poolne suhtlus toimib.

Kui UDP ja TCP on ära määratud, siis tuleb mõelda sellele, mis informatsiooni saadetakse kliendi ja serveri vahel. Üleüldiselt tehakse nii, et saadetaks pakette serveri ja kliendi vahel. Pakette võib olla mitut erinevat tüüpi, igas paketis saadetakse erinevat informatsiooni, näiteks tegelaste liikumise jaoks on pakett, mis määrab ära tegelase koordinaadid, või nupumängus on pakett, mis määrab ära kelle käik on, mis server saadab klientidele kui mängu olek muutub. Näiteks kui mäng on pealtvaates, kus saab tegelasi liigutada, siis oleks üks asi saadetav info tegelas(t)e x ja y koordinaadid. Siin on näiteid pakettidest. Etteantud projektis on paketid tehtud eraldi java klassideks. Paketid võiksid olla võimalikult väiksed, nii et neid saaks võimalikult kiiresti saata. Mida teie saaksite etteantud projektist paremini teha oleks, et iga pakett laiendab (extend) abstraktset klassi mitte tavalist klassi, see on stiili suhtes parem.

Järgmise asjana oleks teil vaja realiseerida suhtlse süsteem serveris ja kliendis, mis võtab paketid lahti ja realiseerib nendega mängu loogikat. Krypnetis käib asi nii, et on vaja teha serverile kuulamise instants (instance) serveri klassi sisse:

server.addListener(new Listener() {
    public void received(Connection connection, Object object) {
        // packetite suhtluse loogika läheb siia
    } 
});

Näidisprojektis on see koht ära näidatud all oleval pildil. Pildil on siis näha kuidas Server saab kliendi (Connection) käest paketi (Object), siis tehakse mingisugune muudatus maailmale ja saadetakse see teistele mängjatele/mängjale. server.sendTCP(mängja ip, muudatuse packet)

Server addListener

Siin on üks skeem sellest, kuidas näidisprojektis klient-server suhtlus toimib.

Game architecture

Lisamaterjalid:

Videod: