dissabte, 25 d’abril de 2009

Cas d'estudi: Gauntlet - Reconsideracions

Moltes vegades, fent jocs, me passa que de repent me costa avançar. Hi ha algo que me molesta, que no quadra. El subconscient me diu que algo no va be. Es una putada, com en els somnis en que vols correr pero no pots, vas molt lento, com baix de l'aigua. Hi ha alguna cosa que no quadra i no se el qué.

Així que esta setmana he estat pensant en quins son els problemes que trobe amb el Gauntlet este. He trobat tres punts a considerar:
- La comunicació per red
- La gestió de events del joc
- La gestió de montonades de enemics

La comunicació per red
Aquest es el problema obvi, en el que estic treballant, per tant no es una sorpresa ni un problema. No obstant, al arrivar ací es quan s'han fet patents els demés problemes. Es, per tant, el encarregat de solventar-los, o al menys, de soportarlos.

La gestió de events del joc
Com ja he comentat, els events importants els ha de determinar el servidor. Quan juguem online, serà el servidor el que ens avisarà de dispars i col·lisions. Però quan juguem offline som nosaltres els encarregats. Com monte un sistema que puga compartir la major part del codi i, al mateix temps, soportar aquests dos sistemes? En un joc offline, conforme vas procesant els sprites trobes les colisions i, directament, actues en consequència. En red tindré que ignorar aquestes colisions i nomes mirar el que m'arriva del servidor.

Encara que una sol·lució podría ser fer-ho condicional i que segons el tipus de joc mirara les col·lisions d'un lloc o altre, me pareix molt poc elegant i escalable. Lo millor seria que el punt d'entrada d'aquestos events sempre fora el mateix, encara que el detonant de l'avis fora diferent.

Per tant, crec que el que tindré que fer es que el motor del client sempre comprova col·lisions i tal, pero en compte de actuar en consequència, tindrà que avisar al proxy, per dir-ho d'alguna forma, enviar-li un equivalent al missatge que el servidor ens envía per red. D'aquesta forma, el proxy, depenent de si estem conectats o no, executa els events que deu executar, i la resta del codi no s'entera d'aquestes diferències. He de repensar-ho un poc més. Estoy en ello.

La gestió de montonades de enemics
En els mapes del Gauntlet sol haver molts enemics, es un dels seus encants. Podrien ahver cents d'enemics en un mapa al mateix temps. Els meus calculs em diuen que molts més. No obstant, processar tants sprites serà molt costos. Es més, no es escalable, ja que depenent del nombre d'enemics el joc pot anar més o menys rapid.

Necessite una sol·lució escalable, que em permeta procesar els enemics d'una forma lineal. Es més, si el servidor s'encarrega de les decissions dels enemics, ha de trobar una forma d'enviar les ordres dels enemics sense saturar la red.

Hi ha una optimització clara: En Gauntlet nomes els enemics que estàn en pantalla es processen. Els demés es queden quetets, inclus els generadors de enemics no generen si no estem en pantalla.

Aprofitar aquesta ventaja no es fàcil amb el sistema d'sprites que tenía pensant. No veia la forma de no tindre que recorrer tots els sprites per a vore quins estaven en pantalla i processarlos.

La sol·lució seria clara si poguera tindre-l's en tiles, com el pepe, per exemple, que un ninotet esta en un tile o en altre. Pero aquestos sprites es mouen al pixel, a més, en un moment donat pot haver dos sprites tocant un tile.


En el que no havia caigut es que, al no poder solaparse els sprites, en realitat nomes hi ha un sprite en cada tile, encara que tinguen un offset de desviació del centre del tile. Encara que visualment estiguen tocant el mateix tile, en realitat nomes un està en cert tile, amb una certa deviació, l'altre està al tile contigu, amb certa desviació.


D'aquesta forma, en compte de tindre una llista d'sprites, cada tile serà un punter a una estructura amb informació del tile: imatge, si bloqueja o no... i el sprite que te dins, que tindrà una desviació en x i en y, per a pintar-se on toca, a part de l'informació que li faça falta.

Per tant, nomes tinc que recorrer els 12x12 tiles (en realitat tindré que procesar un tile més per cada vora, ja un sprite en un tile pot estar parcialment en el tile contigu) que estàn en pantalla i procesar els sprites que hi haja dins. El cost es pràcticament lineal o, al menys, el pitjor cas està controlat i no pot augmentar.

Aquest sistema nomes te una pega: Les bales son més xicotetes i, per tant, es poden solapar. Per tant, es tindràn que procesar apart. Alguna idea? Que penseu? molaria saber les vostres opinions al respecte.

4 comentaris:

  1. Com monte un sistema que puga compartir la major part del codi i, al mateix temps, soportar aquests dos sistemes?

    Per ara sols se m'ocorre una posible solució per a aquesta pregunta, igual no es óptima i fins i tot pot ser que l'hages pensat, es executar el servidor al pc local o conectar-se a un pc remot. Obviament el sevidor s'executaria automaticament. No he desenvolupat l'idea simplement es una idea per si te val.

    ResponElimina
  2. Ie que agonia! Qui inventaria la idea de joc en xarxa? Cada vegada que se m'ocorre una sol·lució me toca tirar-la cap enrere per culpa de la latència. Això i la meua inexperiencia creant jocs d'este tipus fa que me faça mal el cap i tot. He de canviar el mode de pensar.

    ResponElimina
  3. Ja no se si era en esta entrada on posaves els problemes de jugar en red i jugar soles. El cas es que, desde la meua inexperiencia, no pot tindre el mateix programa el modul de red? Vull dir, el servidor eixe que va dient a tots on estan i que pasa en el joc.

    Per altra banda, el tema de les bales i on clavar-les al mapa, al gauntlet nomes podies disparar una bala al mateix temps, amb lo qual no pots posar varies bales sobre un tile a menys que siguen bales de diferents personatjes. Si son bales de malo CREC recordar que s'anulaven. No se si les teues bales es menjaven les d'alguns malos o al reves, pero podría ser una idea a tindre en compte. El problema seria si colisionen dos bales de dos jugadors, en eixe cas no recorde que pasava pero podriem pensar en una solució semblant a la d'abans.

    ResponElimina
  4. Lo de executar el servidor en local, home, es un poc fe rla mà tindre que executar dos programes per a jugar offline.

    Respecte a tindre el modul del servidor, clar, eixa es la sol·lució. El problema no es eixe, el problema es que, normalment, en un joc offline, en el moment que es detecta una colisió, es fa el que es tinga que fer. En red si ha hagut colisió o no ens ho diu el servidor. La solució passaría per fer que, el client al detectar una colisió, en compte de procesarla, cride a un mètode del modul "servidor" (simulant que li arriva una ordre, al igual que passaría per red), i este la propague als jugadors igual que faria si li haguera arrivat per red. Símplement es que has de canviar la forma de pensar com procesar estes coses depenent de si el joc va a tindre multijugador o no.

    Respecte a les bales, el problema no son les colisións, sino que al poder donar-se el cas de que dos bales estiguen en el mateix tile, no puc guardar-les en el propi mapa de tiles. A vore si en el proxim post parle un poc més d'aquestos temes.

    ResponElimina