valós idejű játék programozása PHP-ben
sziasztok
a szabadidomben nekialltam egy jatekprogramot fejleszteni, php nyelven, mysql adatbazissal, egy kis ajax segitsegevel. gyonyoru kodot irtam, de most kezdek belegabalyodni, ezert kerem a segitsegeteket.
tehat a jatek valos ideju, minden akcional az ora elkezd ketyegni, es n masodperc mulva hajtodik vegre az akcio. elmeletileg legalabbis valahogyan igy kene mukodnie. ez reszben mar mukodik, de ahhoz, hogy bovithessem, az eddigi kodba bele kene nyulnom, es ez egyre bonyolultabb, de meg egyszer, utoljara ;-) hajlando vagyok az egeszet atirni.
per pillanat ugy mukodik, hogy jatekosonkent vegrehajt egy _admin_scriptet_, ami a legutolso futas ota eltelt idovel dolgozik, ha az eltelt ido nagyobb, mint egy ora, akkor pedig beleirja a valtozasokat az adatbazisba.
milyen technikat ajanlotok ilyen idozites kivitelezesehez szerver oldalon? lehetoleg minel minimalisabb, atlathatobb, bovithetobb kodot szeretnek irni. googlet mar volt.
nem szeretnem abbahagyni, egyre jobban erdekel a dolog. bar hobbi szinten dolgozom rajta, remelem, egyszer majd csak elkeszul.
valaszaitokat elore is koszonom
ErdosJ
■ a szabadidomben nekialltam egy jatekprogramot fejleszteni, php nyelven, mysql adatbazissal, egy kis ajax segitsegevel. gyonyoru kodot irtam, de most kezdek belegabalyodni, ezert kerem a segitsegeteket.
tehat a jatek valos ideju, minden akcional az ora elkezd ketyegni, es n masodperc mulva hajtodik vegre az akcio. elmeletileg legalabbis valahogyan igy kene mukodnie. ez reszben mar mukodik, de ahhoz, hogy bovithessem, az eddigi kodba bele kene nyulnom, es ez egyre bonyolultabb, de meg egyszer, utoljara ;-) hajlando vagyok az egeszet atirni.
per pillanat ugy mukodik, hogy jatekosonkent vegrehajt egy _admin_scriptet_, ami a legutolso futas ota eltelt idovel dolgozik, ha az eltelt ido nagyobb, mint egy ora, akkor pedig beleirja a valtozasokat az adatbazisba.
milyen technikat ajanlotok ilyen idozites kivitelezesehez szerver oldalon? lehetoleg minel minimalisabb, atlathatobb, bovithetobb kodot szeretnek irni. googlet mar volt.
nem szeretnem abbahagyni, egyre jobban erdekel a dolog. bar hobbi szinten dolgozom rajta, remelem, egyszer majd csak elkeszul.
valaszaitokat elore is koszonom
ErdosJ
google
innen eddig a 3. megoldast hasznaltam, de erdekelne, hogy van-e mas is, illetve, hogy ti mit ajanlotok, mit erdemes, stb..
daemon fut a szerveren...
mondjuk c++-ban irnam meg a program lelket, ami a szerveren megallas nelkul futna (daemon), majd peldaul egy kozos fileon keresztul parancsokat kapna egyeb php fileoktol, azokat vegrehajtana. igy az idoziteseket, adatbaziskezeleseket, miegymast kozpontilag meg lehetne oldani...
nagy hulyeseg, vagy erdemes foglalkozni vele?
valaszaitokat tovabbra is varom
ErdosJ
PHP?
miert php
FELHASZNALOI FELULET ==>ajax engine ==>php feldolgozo==>kozos file==>vegrehajto program a szerveren.
tehat a php file beleirna egy kozos fileba a parancsokat (amelyeket ugyebar ajaxos post-on kap), azt, hogy melyik felhsznalo milyen akciokat kezdemenyez, azoknak mikorra kell befejezodniuk. a program a szerveren pedig allandoan ellenorzi a filet, hogy erkeztek-e uj akciok, ha erkeztek, vegrehajtja idozitve.
lehet, hogy az elso postom nem volt egyertelmu, ezert sorry. tehat:
a jatek ajaxos, es a szerver oldal segitseget igenyli azert, hogy tobben is lehessen jatszani egyszerre, interaktiv modon.
jo, jo, hirtelen ez jutott eszembe, de azert szoljatok, hogy nagy hulyeseg-e.
cron
Webes játék-tapasztalatomból egy olyan példát tudnék mondani, hogy adsz egy parancsot a karakterednek, hogy "Bányássz". Az adatbázisban az utolsó paracs található. Az újabb parancs mindig törli az előzőt. A percenként futó szkript megnézi, hogy mit csinál Ogár, látja, hogy bányászik, akkor hozzáad egy aranyat a pénzéhez. Másnap újra benézel Ogárhoz, és látod, hogy összegyűlt az 1440 arany az új bunkóra, ezért azt a parancsot adod neki, hogy menjen északnak (a közeli városba). A percenként futó szkript csekkolja Ogár státusát, és látja, hogy északra megy, ezért az Y koorinátájához hozzáad 10-et.
Az AJAX-os felület persze percenként frissül, és te látod, hogy Ogár minden percel közelebb kerül a városhoz.
Persze lehetnek azonnal futtatható parancsok, amik nem igényelnek időt. Ilyen például a vásárlás. Vagy olyan parancsok, amikhez idő kell, de csak egyszer kell őket végrehajtani (mondjuk csapdaállítás vagy építés).
Elég kevés paramétert árulál el a játék természetéről, úgyhogy lehet, hogy teljesen el vagyok tévedve. De ha már felmerült a daemon kérdése (tehát vannak épkézláb lehetőségeid a szerveren, nem egy ingyenes szolgáltató guzsbakötött szerveréről van szó). Írhatsz kvázi-démont php-ben is. A socket kezeléssel nyitvatarthatsz élő kapcsolatokat, és azonnal reagálhatsz az eseményekre. A PHP dokumentációban van egy példa CHAT alkalmazás.
Nem csak kvázi
nem ertem
RTFM
miert nem cron
nem hiszem, hogy a cron tuttijo megoldas, mivel a jatekom nem kor alapu. de vehetjuk ugy is, hogy kor alapu, csak minden kor egy mp-ig tart. igy viszont a cronnak masodpercenkent kene futtatnia, mi nem tul jo otlet.
az en jatekomban nekiallok epitkezni, es n mp mulva felepul az epitmeny. viszont a kulonbozo akciok nem egesz percenkent hajtodnanak vegre, es ez adja a nehezseget.
ez a socketezes hogyan mukodik? hogyan tudnek php-bol egy mar futo (daemon szeru) programnak parancsokat kuldeni, es visszajelzest szerezni?
Cron
A probléma koránt sem triviális sajnos, mivel nagyon sok részfeladata van és nagyon sok időzítés van. Két fajta megközelítést tudok ajánlani:
1. az egyszerűbbik módszer. Valaki elindítja egy mézessüti építését, akkor az bekerül egy adatbázis táblába. Legközelebb amikor valaki csinál valaki valami mézessütitől függő dolgot, akkor az a programrészlet megcsinálja a már elkészült mézessütik átállítását...
Ezzel az a probléma, hogy könnyebben törhető a játék és egy idő után nagyon lassúak lesznek a lekérések.
2. a bonyolultabb módszer. Kell egy daemon, amelyik az időzítést ellátja. Több szál, az egyik szál csak a mézessütikkel foglalkozik, nézegeti mi mikor készül el, megszakítások, stb.
Ezzel meg az a probléma hogy nem érzem reálisnak azt, hogy egy ilyet belátható időn belül megírj. Ehhez kell a Unix rendszerprogramozástól kezdve a PHP elég mély ismeretéig minden.
Van még egy köztes módszer is, amiből valószínűleg mind a kettő árnyoldalait fogod ki, méghozzá hogy írsz egy daemont ami az alapvetően időzítendő feladatokat ellátja, a többi meg valós időben történik...
Összegezve, nem érzem reálisnak azt, hogy Te egy ilyen szoftvert megírj. Ha százalékot kellene mondanom, itthon a webfejlesztő cégek 80-90%-a nincs fölkészülve egy ilyen feladatra. Próbálkozni persze lehet, csak kezdd kicsivel és számíts rá, hogy nagyon, nagyon, nagyon sokszor fogod újratervezni az egészet.
vegyes valasz
a cronnal amugy sem vagyok kibekulve, szoba sem johetne, mivel valos ideju jatekrol van szo.
1: eddig az egyszeru modszerrel probalkoztam, gyonyoruszep objektumorientalt php programot irtam, haromszor (!) ujraterveztem, es meg mindig nem tokeletes.
2: ezt a modszert szeretnem megprobalni.
csak konyorgom, ne toljatok le ennyire!
igen, ezt hobbibol csinalom, egy darab "fejleszto" vagyok, civilben gimnazista. ez viszont a hobbim (tehat semmilyen anyagi erdekem nem fuzodik hozza, es nem a nagykozonsegnek csinalom), tudom, hogy nem egyszeru, viszont megis megoldast keresek ra. ha daemont kell irni, hat gyakorlom a c++-t, es megirom! es ehhez (is) kerek segitseget.
c--
Inkább nézd át a PHP ilyen irányú képességeit. (Kevesebb hibalehetőség és még gyakorlatod is van benne).
Tervezésnél tényleg azon gondolkozz, hogy a "körök" lassíthatók legyenek, tehát esetenkéánt tarthasson már 1.5 másodpercig egy kör, ha annyi ideig tart feldolgozni a világot. Ha belaggol a játék, akkor belaggol, de ha ez nincs tudatosan kezelve, sokkal súlyosabb logikai hibák léphetnek fel.
miert php?
azert valasztottam volna a c++-t, mert valahogy ugy kepzeltem el, hogy:
amikor valami akcio indul (pl socketen keresztul ertesul a dologrol), akkor elkezd visszaszamolni, es amikor nullahoz er, vegrehajt egy mysql lekerdezest, az akcio tipusatol fuggoen.
hja, erre a legszebb megoldas a javascript lenne!
Miért a visszazámlálás?
miert java?
es hogy miert viszaszamlalas:
tehat a grafikus feluleten megnyomsz egy gombot, mire elkezd visszaszamolni az oldal, es ha nullara er, akkor frissiti a lapot. nna, ez mar mukodik kliens oldalon, most szerver oldalon szeretnem megcsinalni ugyanezt. de ha van jobb megoldas a visszaszamolasnal, akkor kivancsian varom. tenyleg.
érdemes lenne megnézni még
A közös fájlt meg már megvalósították mások, adatbázisnak hívják. :D Szerintem ne kezdj el kerekeket feltalálni. :P
Re: érdemes lenne megnézni még
a c#-ot mar hasznaltam, egyedul az aggaszt, hogy nem minden szervergepen van mono, es en a minden szempontbol optimalis megoldast keresem. ugyanez a bajom a javaval.
a perl mellett dontottem, a daemon mar kesz, kozos file helyett socketeket hasznal. (igen, a kozos file talan tenyleg hulyeseg..)
Saját szerver..
Re: Saját szerver..
ha iskolai szerver eleg lesz, az jo, ha nem lesz eleg, az megjobb.
Chat példa
Én így csinálnám: Egy szkript (átlagos PHP) megkapja az AJAX hívást. A klienstől kapott parancsot egy timestamp-el ellátva bepakolja az adatbázisba. Egy állandóan futó PHP szkript feldolgozza a beérkezett parancsokat (az adatbázisból) a timestamp sorrendjében. Persze figyelve, hogy az egy másodpercben kiadott parancsok egy körre vonatkoznak, például, ha két játékos támajda egymást, akkor nem csak az első támadást kell végrehajtani, és nullára csökkenteni a másik életerejét, hanem a másik támadása is végrehajtódik, mert csak a következő kör elején hal meg az ellenfél.
És itt jön a probléma a másodperces körökkel. Mi van, ha több ideig tart a szervernek a kör feldolgozása, mint 1mp?
chat szerver
Szerintem, nem triviális a feladat, koránt sem. Én nem tudom kapásból azt mondani, hogy tudom rá a megoldást.
ez az.
az neheziti a gondot, hogy az en otletem nem tul szokvanyos.
Nme mindig 1sec az 1sec
socket
az megoldhato, hogy socketeket keresztul kommunikaljanak a scriptek a daemonnal (amit c++-ban szeretnek megirni ugyebar)?
hu, bonyolodik.
Gyors az
Application server
A szerveren belül meg meg kell oldanod, hogy a belső működés jó legyen. Én nem javaslom a körökre osztást, bár lehet hogy nem tudod elkerülni.
Szerintem, ha az elsőt kifogástalanul meg tudod csinálni, az már nagy előrelépés. Aztán írhatod meg a játék enginet. :D
tippek
1.egy tablaba eltarolod, hogy milyen parancs, mikor, fusson le. aztan irsz egy scriptet, ami annyit csinal, hogy kiolvassa ezt a tablat, az idoket veve alapul, es amelyik parancsnak "lejart" az ideje, azt futattja. aztan ezt a scriptet, minden lapletoltodesnel futtatod.
nyilvan valamilyen zarolast is kell hasznalnod, illetve egy kis cron segitseget is igenybevehetsz, arra az idore, ha senki se kattintana hosszu ideig, bar ha senki se kattint, akkor lehet nincs is mit szamolni. :)
persze ez igy fake, de legalabb egyszeru.
2. irhatsz demon-t is, ott tulkepp a demon-nak odaadod a parancsot, ami indit egy timer-t, es ha lejar lefutattja, en python-ba irnam. ;)
de ha bonyolitani akarod:
3. ha mar visszajelzest is akarsz lehetoleg real-time-ban, akkor szinten demon-t kell irnod, de akkor mar valamilyen kezdetleges protokolra is szukseged lesz, kliens oldalra javaslok egy java socket gateway-t(google-ba megtalalod) ez csatlakozik a demon-hoz, es fenntartja a kapcsolatot. aztan evvel a java progival kell kommunikalnod js segitsegevel, ez viszonylag egyszeru pl. firefox-nal, ie-nel mar nem. annyi kulonbseg, hogy a java-ban levo fuggvenyeket mindket esetben tudod futtatni js-bol, mig a java-bol, csak firefox-al tudsz js fuggveny-t futtatni.
valoszinu tobb problemad is lesz meg. :)
4. a demon tulkepp marad, de a kliens oldalt, pl. tisztan java-ba, vagy flash-ben irod meg.
u.i.:egyebkent leirhatnad szajbaragosabban is a jatekot, mert szamomra meg mindig zavaros. :)
Re: tippek
koszonom a valaszodat.
1) eddig ez volt. gyonyoruen mukodott, de a kod gyakorlatilag bovithetetlen. az a problema, hogy bizyonyos akciok fedik egymast, egyiknek szuksege van egy masikra, stb.
2) iggen, most ezen dolgozom. en perlben irom. (es most a socketkezelessel szivok.)
3),4) flash sajna szoba sem johet, a java-t pedig sajna nem ismerem tulsagosan (egy hellovilag meg elmegy.)
ha meg mindig nem vilagos, akkor sorry, megprobalom az elso postot szerkeszteni.
a jatekrol konkretan.
minden jatekos egy fold meretu ;-) bolygoval kezd. ezen a bolygon tud epitkezni, fejleszteni. egy epitkezes, fejlesztes ugy mukodik, hogy amikor megnyomtam a gombot, visszaszamol az oldal (meg van hatarozva, hogy egy epitkezes/fejlesztes milyen hosszu ideig tart.), majd amikor nullahoz er, az epitkezes/fejlesztes befejezodik.
tehat valos ideju. idaig tokeletesen mukodik, de a kovetkezoket mar nem tudtam belezsufolni a kodba:
nem csak epitkezni/fejleszteni lehet, hanem (az epuletek szintjetol fuggoen) bizonyos egysegeket gyartani, tamadni, vedekezni, kereskedni (a flotta is meghatarozott ido alatt jut el a jatekoshoz).
nem értem
Mindegyikhez kell idő. Ugyanúgy kell kezelni mint az építkezést. X mp + Y nyersanyag = level 2-es épület, X mp + Y lakóhely + Z nyersanyag = katona, egységtől függő X mp = 1 egység megtétele a térképen...
Én ezeket kliens oldalon csinálnám meg, és csak adminisztrálnék szerver oldalon. Csak azt kell megoldanod, hogy a játékosok mozgását is meg tudd jeleníteni mindenkinél (közeledik az ellen, támad stb.) A problémát ez jelenti, hiszen ehhez valamilyen server-push megoldás fog kelleni neked, amit lehet COMET-tel, bár ezt még sosem próbáltam... Használhatsz flash-t. Ez a játék felületét is látványossá teheti, valamint tud socket-eket kezelni, így a játékszervered nem egy webszerverben futó php script lehet, hanem egy rendes alkalmazás, rendes tcp/ip kapcsolatokkal, kétirányú kommunikációval. Írhatod amiben tetszik, én biztos nem php-ban írnám...
Re: nem ertem
most mar egeszen jol haladok, perlben nekialltam a daemont megirni, socketkezeles mar kesz,adatbaziskezeles meg hatra van.
az, hogy php/java/flash... en a javahoz nem ertek olyan szinten, hogy socketezes, adatbazisozas, minden menjen. flash-hoz meg anynira sem. igy maradt a php+valami mas paros. igy is, amit csak lehet, kliens oldalon oldok meg, ajax segitsegevel.
ezért nem jó a php
Kliens
törés, csalás
Persze ez nem igazi csalás, csak spórolhat valaki a klikkelésen és tonnaszám gyárthat majd egységeket, ha van elég erőforrása, nem kell keresgélni a "gyárat" kattintgatni rajta stb. Ezzel is előnybe tud kerülni a becsülettel játszókkal szemben.
Erre csak olyan megoldást látok, hogy a saját protokoll-t titkosítani kell, hogy ne lehessen könnyen visszafejteni. Esetleg korlátozni az egységnyi idő alatt küldhető parancsok számát vagy valami ilyesmi... Ezzel szívtunk annó, igaz a mi játékunk nem real-time volt, hanem körökre osztott stratégia.
Rossz megközelítés
Én még bátorítanám is a szkriptelést. Valakinek érdekesebb lehet botot írnia, mint maga a játék. A szabályoknak kell kivédeni, hogy a valódi játékosok ne kerüljenek hátrányba a szkriptekkel szemben. Ha kiküszöbölsz a játékból mindent, amiben jobb egy gép, akkor a logika, stratégia lesz ami jóvá tesz egy játékost, nem pedig az, hányszor tud kattintani, ez érdekesebbé teszi a játékodat emberi lények számára.
Más: egy netes játékban nincs csalás! Mindaddig, amég nem törik fel a szereredetcsak a Te általad adott lehetőségekkel élnek. (Esetleg felfedezik a tervezési, logikai hbáidat).
real -time
abban az esetben eleg az ajax, ha belefer egy pl. 30mp-kenti frissites, de abbol amit leirtal, nekem az jott le, hogy nem fer bele.
COMET
Üdv,
Felhő
jo, hogy mondod
de amit eddig felfogtam belole az alapjan, lehet jobb valasztas (hosszabb tavra gondolvan), egy java kliens erre a celra, vagy a szerver oldalon kell nagyon ugyesnek lenni. :P
Comet
Comet hááát
böngészőből?
Üdv,
Felhő
applet
ez is comet
Üdv,
Felhő
tobbnyire kesz.
most keszultem el a daemon elso valtozataval.
mar mukodokepes, van benne socketkezeles, adatbaziskezeles, tokeletesen mukodik a php filejaimmal.
az egeszet PERL-ben irtam meg, tomboket hasznal meg ciklusokat, es eleg gyors (kicsi gepemen nehany ms-t eszik.)
mivel a PERL nem az erossegem, esetleg arra tudnatok nehany bolcs tanacsot mondani, hogy hogyan tehetnek egy ilyen jellegu kodot meg gyorsabba, hatekonyabba, biztonsagosabba?
minden eddigi hozzaszolast nagyon koszonok, sokat segitettetek.
PERL
Re: PERL
neked mar vannak ezzel kapcsolatban rossz tapasztalataid?
a projekt ma.
gondoltam, kozzeteszem, hogy a projetk most hogy all, de iskola mellett nincsen tul sok idom ra :(
a daemon eleg jo, json adatokat kuld a szervernek, ami pedig a klienssel kommunikal. azota egyszer mar ujrairtam.
most azon dolgozom, hogy legyen benne utemezes is.
erre celszeru megoldas lenne a cron hasznalata, de felmerult az a problemam, hogy mar igy is tul sok reszbol all a program, es attol tartok, hogy mar tenyleg nagyon atlathatatlan lesz.
arra gondoltam, hogy erdemes lenne-e az utemezest is a (perl) daemonomba beepiteni? vagy a cron gyorsabb/biztonsagosabb/hatekonyabb/jobb?
perlben daemon irasakor jo vegtelen ciklust hasznalni, vagy van hatekonyabb megoldas is?
valaszaitokat varom
ErdosJ
Daemon...
Re: Daemon...
a vegtelen ciklus mennyire szerverbarat?
semennyire
Re: semennyire
Aktív várakozás
A nagyobbik baj, hogy ha egyszerre sok feladat szakad a szerverre, be fog lassulni a játék, mert a feladatok egymás után hajtódnak végre, nem pedig több szálon, ahol az ütemezö futhatna egy önálló szálon.
Re: Aktív várakozás
perlben van mod tobbszalusagra?
nnah, megyek, utanaolvasok.
Passz
Egyébként zárójelesen megjegyzem, nem hiszem hogy a Perl (ami alacsonyabb szintű mint a PHP) ne tudja ezt, amikor a PHP már tudja.
Re: Passz
tehat lehet, hogy erdemes lenne ket fo szalra bontani a scriptet, az egyik a lekereseket kezelne, a masik pedig aludna vegtelen ciklusban? akkor pedig mar nem eszerubb ket kulon script filet kezelni? innen pedig mar tenyleg egy lepesre van a cron hasznalata..
azert nem szeretnem a 'lekerdezesek kezeleset' is tobb szalra bontani, mert a 'lekerdezes' tulajdonkeppen abbol all, hogy egy sokdimenzios tombon muveleteket hajt vegre. es mi van akkor, ha a ket szal egyszerre akar muveleteket vegrehajtani a tombon, vagy bejarni a tombot? nem fognak osszekavarodni a szalak?
event queue
Re: event queue
ha jol ertem a sorbaallitas lenyeget.. akkor azzal fogok szivni, hogy nem minden esemeny tart ugyanannyi ideig. ergo mindig meg kell vizsgalnom, hogy a sorban hova szurjam be az esemenyt. itt viszont visszaterek a tombok hasznalatahoz.
kifejtened bovebben? es hogyan hasznalhatnek tobb sorbaallitast?
Strukturálás
Másik lehetőség ha például vannak azonnal végrehajtandó parancsok, ezek mennének az egyik queue-ba és vannak amik az aktuális állapotokat egyáltalán nem változtatják (időzített dolgok?) ezek pedig egy másikba. A magasabb prioritással futó szál kezeli az első sort, a másodiknak pedig elég egy kisebb prioritás stb stb...
Ha nagyon sok queue-t használsz az persze lassít a dolgon, de egy ilyen méretű projektnél 5-6 különböző sorbaáállítást símán el tudnék képzelni. Maga a parancs feldolgozása sem kell hogy egytlen logikai lépés legyen. Gondolkodhatsz itt is abban, hogy különböző parancsokra más-más thread-ek működnek.
Queue
Re: Queue
Nem jó annyira
Re: Nem jó annyira
koszonom, neki is allok megcsinalni.
Wait