Navigate / search

S1E13: Hogyan írjunk online játékot?

Egy hónappal ezelőtt Balázstól kaptunk egy igen érdekes kérdést: böngészős játékot szeretne írni.

Kedves Balázs! A böngészős játék írása talán a legtöbbet kérdezett, ám legkevesebbet megválaszolt kérdés a szakmai körökben. Műszakilag rengeteg minden kell hozzá, éppen ezért nem kis fába vágod a fejszédet. A kérdésedet annyira jónak éreztük, hogy szeretnénk megajándékozni a Javascript – The Definitive Guide című könyvvel és projektedhez sok sikert kívánunk.

Kezdjük a könnyű részével. A játékvilág ábrázolásához sokan az úgynevezett izometrikus látásmódot választják, ugyanis az ilyen játékelemeket még közepes rajztudással is meglehetősen egyszerű elkészíteni. Ebben az ábrázolásban két dimenziós alkotóelemeket rajzolunk, majd helyezünk egymásra. Ezek a spriteok.

A spriteok elkészítéséhez két képzeletbeli vonalat rajzolunk fel, amik a vízszintessel körülbelül 30 fokos szöget zárnak be. Az spriteok vonalai pedig egymással teljesen párhuzamosak, nem közelítenek egymáshoz, mint egy valódi 3D nézetben.

Amikor a teljes képet rajzoljuk, először rajzoljuk a hátrébb lévő elemeket, majd erre rá az előbb lévőeket. Természetesen egy játékmezőn belül is használhatunk több sprite-ot, amely esetben el kell tárolnunk a spriteok sorrendjét.

Nade, nézzük, hogyan is néz ki ez a gyakorlatban.

Természetesen a játékmotor nem fogja ilyen változatosan leszórni az elemeket, hanem mindig szigorúan hátulról előre haladva dolgozik. Szerencsére ezzel vajmi kevés dolgunk lesz, hiszen kész játékmotorok egész hada várja, hogy bevessük őket. Ezekről egy igen kiváló áttekintést nyújt a html5gameengine.com oldal. Itt nem csak izometrikus játékok készítésére alkalmas motorokat találunk, hanem többek között WebGL-t támogatókat is. Ilyen például a HelloRun alatt futó three.js is.

Ha választottunk frontend game enginet, ideje rátérni a backendre. A technológia kiválasztásánál körültekintően kell eljárni, a játékműködéstől függően nagyon különböző megoldásokra lehet szükségünk.

Az olyan nyelvek mint a PHP jók, ha hagyományos alkalmazásokat kell írnunk, viszont egy játék alatt hamar elvérezhetnek. Első játékként mindenképpen próbáljunk meg olyat készíteni, ami nem alapul két játékos közötti közvetlen interakción. Példaként megnézhetjük a temérdek Travian-klón egyikét, ahol a támadások ütemezve zajlanak le, előre tudható, hogy mikor kell feldolgozni a támadás eseményét.

Kezdetben itt elegendő lesz egyetlen feldolgozó szál, ami percenként fut. Ezt akár a rendszer crontabjából is el tudjuk indítani és feldolgozzuk az aktuális feladatokat. Egyetlen dologra kell csak figyelnünk, hogy a feldolgozó szál zárolja saját magát, ne tudjon véletlenül kettészer elindulni párhuzamosan. A későbbieben, ha szükség lesz rá, bővíthetjük a kapacitást és beüzemelhetünk egy úgynevezett queue rendszert is.

Ha olyan játékot írunk, amihez közel valós időben kell reagálni, akkor a HTTP protokoll helyett érdemes megfontolni a Websocketek használatát. NodeJS-sel és socket.io-val néhány milliszekundumos késleltetéssel tudunk üzeneteket eljuttatni az egyik játékostól a másikhoz. A NodeJS egy további előnnyel is rendelkezik: JavaScriptben írhatunk szerver oldali programokat.

Hogy ne csak elméletről legyen szó, készítettünk egy pici minta játékot a Phaser nevű keretrendszer segítségével. A forráskód mintegy 140 sornyi JavaScriptből áll és a github.com/webtudor/s1e13 oldalon érhető el tanulmányozásra.

Végezetül, de nem utolsó sorban szóljunk az üzleti modellról is. A böngészős játékok elég erőforrás-igényesek tudnak lenni, ezért egy közönséges webtárhely valószínűleg nem sokáig elegendő. Innentől kezdve pedig megugranak a játék üzemeltetésével kapcsolatos költségek is, tehát bevételre van szükség. Ráadásul abban a szerencsétlen helyzetben vagy, hogy a piac szép lassan telítődik és a játékosok már nem hajlandóak belemenni az olyan játékokba, amelyeknél fizetés nélkül óránként vissza kell jönni és etetni a tamagocsit. Éppen ezért érdemes vagy nagyon kicsi és nem erőforrásigényes játékot írni, vagy jól átgondolni, hogy miből kerül finanszírozásra a projekt.

Köszönjük Balázsnak ezt a kiváló kérdést. Ha Neked is van kérdésed és fel szeretnéd tenni, látogass el a webtudor.net/kerdesek weboldalra.

Comments

Auth Gábor
Reply

Hi,

Néhány észrevétel, javaslat, ötlet, mint gyakorló játékfejlesztő… :)

“Műszakilag rengeteg minden kell hozzá, éppen ezért nem kis fába vágod a fejszédet.”

Ha az ember egyedül kezd neki, akkor nem csak műszakilag kell rengeteg minden, hanem mindenféleügyileg kell rengeteg minden: a teljes stack kezelése az üzemeltetőtől kezdve a fejlesztőn, grafikuson és tesztelőn át a menedzserig és pénzügyi emberig mindenre szükség van. Mármint akkor, ha az ember komolyan gondolja… :)

“Ezekről egy igen kiváló áttekintést nyújt a html5gameengine.com oldal.”

Ez egyébként kicsit megtévesztő és szerény véleményem szerint félrevezető is, mert jelenleg az új casual játékok nagyon-nagyon-nagy része mobilon jön ki először, mobilon pedig a fenti keretrendszerekből nagyon szép képregény lesz csak mobilon, a WebGL alapú megoldások pedig szinte alig működnek, ha mégis, akkor ott is egy nagyságrend a különbség teljesítményben.

Szóval ha cél a mobil platform is – márpedig cél, akkor a Javascript felejtős. Nagyon felejtős! Helyette el kell dönteni, hogy melyik az elsődleges platform: az iOS vagy az Android.

Mind a kettő esetben van lehetőség arra, hogy a másik platformon minimális teljesítményvesztéssel működjön a program, az iOS-Android irányt nem ismerem, de az Android-iOS irányra teljesen jól működő megoldás a Libgdx, elég sok alkalmazás használja, minimális köret kell csak iOS-on a Libgdx core modul köré.

De az egyik esetben Java nyelven kell fejleszteni, a másik esetben ObjC és/vagy Swift. Mindegyik eléggé messze van a Javascript-től.

“Az olyan nyelvek mint a PHP jók, ha hagyományos alkalmazásokat kell írnunk, viszont egy játék alatt hamar elvérezhetnek.”

Sok minden más is el tud vérezni, például azon, hogy szerver oldalon teljesen másképp kell gondolkodni, mint a kliens oldalon… :)

“A NodeJS egy további előnnyel is rendelkezik: JavaScriptben írhatunk szerver oldali programokat.”

Ami csak akkor előny, ha van a rakás JS fejlesztőnk a padláson vagy a spájzban, akiknek épp nem tudunk feladatot adni _és_ a szerver oldal buta, nincs benne logika vagy komplex számolás. Amint lesz ilyesmi és nem csak egy brókerként funkcionál, a NodeJS akadozni fog, márpedig egy játékban a szerver nagyon sok mindent ellenőriz, nem hihet a kliensnek, a kliens csak megjelenít és csak a megjelenítéshez (=élvezhető játékmenethez) szükséges logikákat tartalmazhatja.

Szóval ha nincs Javascript fejlesztő a spájzban és a kliens oldal se Javascript, akkor felejtsük el a szerver oldali Javascript-et… nézzük körül, van sok egyéb más megoldás, amelyek jól működnek, ha pedig az Android az elsődleges mobilplatform, akkor a szerver oldalra is próbáljunk Java-t tenni (hogy Java EE vagy Spring vagy bármi egyéb, az más kérdés).

“Kezdetben itt elegendő lesz egyetlen feldolgozó szál, ami percenként fut. Ezt akár a rendszer crontabjából is el tudjuk indítani és feldolgozzuk az aktuális feladatokat.”

Ezt nagyon gyorsan felejtsük el. De tényleg!

Ez az eredményezi, hogy a szerver tüskékkel lesz terhelve percenként és ennek a percenkénti terhelésnek az ideje a felhasználószámmal és/vagy egyéb objektumok számosságával lineárisan növekedni fog. Először percenként egy másodperc, aztán tíz, aztán fél perc és a felhasználók azt látják, hogy a szerver szaggat vagy folyamatosan lassú.

Fordítsunk időt “szimulált játékidő” megértésére, az eseményvezérlésre, illetve arra az elvre, hogy az erdőben a kidőlt fának nincs hangja, ha senki nem hallja! Ez utóbbi a legtakarékosabb megoldás, minden objektum esetén eltároljuk az utolsó frissítés idejét és az interakcióknál kiszámoljuk az eltelt idő változásait minden érintett objektumra, ha nem megy az egy képletben való integrálás, akkor lehet szimulálni egy közönséges ciklusban az eltelt perceket is.

A lényeg az, hogy a szerveren legyen szétkenve a terhelés, mert a szerverért teljesítmény alapon fizetünk… legyen terhelve folyamatosan. Annak nincs sok értelme, hogy veszünk egy drága szervert sok pénzért, hogy percenként pár másodpercig mind a nyolc CPU dolgozzon a frissítésen és SSD kell alá, hogy gyors legyen, amikor elég lenne egy tized akkora gép tized annyi pénzért.

Ugyanakkor ne feledkezzünk meg arról, hogy ha véletlenül bejön a játék, akkor ne csak vertikálisan tudjuk skálázni egy darab nagyobb szerverre, mert előbb-utóbb elérjük a maximális szerverméretet és nincs tovább, illetve ha ez a szerver megdöglend, akkor sincs tovább. Olyan architektúrát építsünk fel, amelyik sok kis szerveren (=horizontálisan skálázható) képes működni, mert sok kis szervert jobban lehet cloud-ban üzemeltetni, mint egy nagyot. A szerverek számával könnyebben lehet játszani, mint a szerver méretével, mert általában csak felfelé skálázható a szerver, lefelé már nem.

“Éppen ezért érdemes vagy nagyon kicsi és nem erőforrásigényes játékot írni, vagy jól átgondolni, hogy miből kerül finanszírozásra a projekt.”

Lehet hobbi is… havi 100 dollárból már egészen nagy szerverparkot fel lehet építeni és ez a 100 dollár a mi szakmánkban nem olyan nagy összeg, csak napi két kávé ára a céges büfében… :)

Leave a comment

name*

email* (not published)

website