dijous, 30 d’abril de 2009

Pregunta a tots: API per a JailGames

M'agradaria que m'ajudareu a pensar una API xula per a fer jailgames, al estil de les que feiem per als jocs de pascal, tipo Grafix o DirectMon. Les APIs que fan falta són de video, de audio, de teclat/ratoli/pad i de red. Cregueu que faria falta definir algún grup de funcions més com a API?

Les de só i red son les mes clares que tinc. La de video es la que més m'interessa que me comenteu com la farieu, o qué cregueu que deuria incloure.

Tampoc es questió de matar-se i, per perea, no fer res. Prefereixc no escriure lo que per ara tinc pensat per a no influenciar-vos.

Es més, potser cregueu que no fa falta crear APIs per damunt de SDL, que ja es una api. En realitat jo ho he estat fent per a siga més facil fer certes coses i amb molt menys codi, millor per a començar i fer un joc ràpidament, pero perdent posibilitats.

Ale, espere respostes.

dimecres, 29 d’abril de 2009

Masters of Doom

He tingut poc de temps esta setmana. Lo poc que ho pogut fer ha sigut començar una classe per a poder escriure text (ho necesite per a escriure la IP del servidor, per a escriure els missatges de xat entre jugadors...), pensar una especie de consola que puga conectar a qualsevol joc i escriure comandos, i a passar el Gauntlet del motor OpenGL al motor per software que usa el Arounders. Açò últim, més que res perque no me fa falta acceleració hardware per a jocs d'aquest tipus, però a més perque me restringeix a textures de 256x256 com a maxim si vull que funcione en acceleradores antigues o cutretes (la típica acceleradora Intel que va integrada en moltes plaques, per exemple). Lo dels 256x256 es un fer la mà, perque no em permet ni tindre una pantalla de 320x200. Així que, com no me fa falta, pues torne a l'anterior, que també anava molt be, i au. Ja usaré OpenGL en altres projectes.

Per altra part, este cap de setmana he "devorat" el llibre "Masters Of Doom". Tracta dels inicis de ID Software, sobretot centrant-se en John Carmack i John Romero, desde que eren uns adolescents locs fins al Doom III, pasant per totes les alegries i problemes que tingueren. Es narrativa, res tècnic. M'ha agradat molt, el recomane a tot jailer que guste de fer jailgames. Si en Google busqueu "masters of doom pdf", desde el primer enllaç, que es de RapidShare, podeu descarregar-lo en PDF. De comprar-lo tindrà que ser a Amazon o similar, no l'he trobat en Fnac, El Corte Ingles i similars. Jo me l'he llegit desde el iPhone, que ja s'ha convertit en el meu lector de llibres i webs.

Lo següent que me vull llegir son el "Black Book" de Michael Abrash i el "Red Book" de OpenGL (i el "Fat Book" de Petete... jejeje... que xorrada ¬_¬')

Si no passa res, esta vesprada escric un post parlant del nou sistema de mapa+sprites.

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.

dijous, 23 d’abril de 2009

Cas d'estudi: Gauntlet - Part Vb: Red

En aquest post vaig a parlar dels punts fonamentals a tindre en compte al desenvolupar una arquitectura de comunicació per red en temps real per a videojocs.

Consistencia
Tots els jugadors deuen vore el mateix: Els enemics han de estar al mateix lloc i fer el mateix, el mapa he de trobar-se en el mateix estat, els objectes deuen estar al mateix lloc, etc... Però, a més, ha d'haver un consens respecte a les accions importants, com que una bala toque a un enemic, o a un jugador.

Respecte al nostre joc en particular, hi ha una serie de punts que deuen mantindre una certa consistencia, i cada un requereix d'un grau major o menor de consistencia:
- La posició dels jugadors mentres es mouen: consistencia baixa
- La posició dels enemics mentres es mouen: consistencia baixa
- Els canvis de direcció dels jugadors: consistencia normal
- Els canvis de direcció dels enemics: consistencia alta
- La posició dels jugadors al disparar: consistencia alta
- La colisió entre una bala i un enemic o jugador: consitencia alta

Hi haurà més punts a tindre en compte, pero aquestos ja ens valen per a fer un anàlisis.

Si vos fixeu, he dit que la posició dels jugadors o els enemics requereixen consistencia baixa. Açò es així perque el fet que un jugador estiga uns pixels desviat en un comp que en altre no afecta seriament a la consistencia del joc. Imagineu la consistencia com la similitud entre la versió del joc que te el servidor i la que té el jugador. Hi ha accions, com la posició d'un jugador mentres corre, que no requereixen que siguen exactament iguals en els dos comps. No obstant, la posició des d'on eix una bala o la colisió d'una bala amb un enemic ha de ser exacta entre tots els comps.

Les accions que no requereixen una consistencia alta poden ser executades pel client sense esperar confirmació del servidor. Està clar, de totes formes, que no podem permetre que aquestes accions es desvien massa de la versió del servidor, pero per a això usarem mètodes de sincronia. En realitat no es tracta de trobar quines accions deuen ser consistents, ja que totes deurien ser consistents, sino les que podem cedir un poc de consistencia a canvi de que la jugabilitat millore.

Les accions que requereixen una consistencia alta deuràn fer-se (o al menys prendres la decisió) en el servidor, que propagarà aquesta decisió als demes comps. De totes formes, reduïrem aquestes accions a la mínima expresió.

Per exemple, al nostre joc, els enemics tindràn un comportament determinista, o siga, que no tenen cap component aleatoria al seu comportament. Bàsicament, un enemic calcula quin jugador te mes prop i va a per ell. Com la posició d'un jugador no te perque ser del tot consistent en tots els comps, en un comp un enemic podria triar a un jugador i el altre comp a altre jugador, trencant totalment la consistencia, ja que l'enemic duria rutes diferents en cada comp. Per tant, el que farem es que eixa decisió, la de triar a per qui va, es faça en el servidor, mentre que el moviment cap a eixe jugador es farà en el comp del client.


Sincronia

Havem parlat de la consistencia. La consistencia el que farà es mantindre nugades les coses que controla. Pero les coses que no controla al ditet estaràn un poc soltes i, si no es busca un mètode alternatiu de control, acavaràn desviant-se sistèmicament. Per a evitar que les accions poc consistents es degraden usarem mètodes de sincronia.

Els métodes de sincronia el que faràn es revisar que les accions poc consistents no s'estàn tornant massa inconsistents. Per exemple, que la posició del jugador en el comp del servidor no es massa diferent de la del comp del jugador.

Per a tal cosa enviarem junt a la informació de canvi de moviment de cada jugador, la posició d'eixe jugador en el servidor, de forma que els clients puguen corregir-la donat el cas.


Seguretat

Si el client te massa decisions al seu carrec pot fer trampes. Per exemple, si es el client el que envia la senyal de que la meua bala a tocat a un altre jugador, eixe client pot fer trampes inventant-se ordres imposibles en el joc, amb una versió hackejada del joc, per exemple. Pitjor encara, pot fer un xicotet programeta que envie paquets UDP al servidor amb eixe tipus de ordre, de forma que imposibilitaria als demes jugadors jugar la partida.

Per tant, es important que el client no tinga més responsabilitats que les seues propies decisions, i que aquestes responsabilitats estiguen restringides al que es possible fer.

Per tant, el client nomes enviarà ordres de cap on està caminant i si ha pulsat dispar. Es més, ni tan sols enviarà la seua posició, que podria ser un exploit al poder inventar-se una nova posició i teletransportarse. El jugador començarà en una posició, coneguda per tots, i després nomes transmetrà ordres de "ara camine cap a la dreta", "ara pare", "ara camine cap a l'esquerra", que permetràn a tots els comps recomposar la sequencia. Ací es on faràn falta els mecanismes de sincronia per a que cada comp no estiga interpretant l'escena d'una forma diferent, ja que la latencia pot fer que en uns comps el temps entre tecla polsada i tecla soltada pot ser diferent.


Escalabilitat

No vaig a mirar molt el tema de l'escalabilitat. L'unic pas a favor que he fet es triar una arquitectura client-servidor, i llevar la responsabilitat de ser servidor als clients per a deixar un servidor dedicat.

En jocs de molts jugadors, com els MMORPG, lo normal es que no hi haja un servidor, sino un cluster de servidors, que deuen sincronitzar-se entre sí. Aixó s'escapa del nostre objectiu.


En el proxim post parle de la classe que controla al jugador i de la classe proxy que manté la comunicació.

dimarts, 21 d’abril de 2009

Poc de temps

Ie, que estic viu. Este cap de setmana apenes he fet res. No, no he esta viciant-me like loc a la PSP, apenes he pogut probar-la i jugar un poc en la sobretaula. Ni tan sols he pogut fer alguna proba de demo.

He estat dissenyant el sistema de comunicació per red del Gauntlet. Vaig dir que aniria fent poc a poc, pero es una perea enorme, perque no es tan facil com anar afegint coses sino que al millorar el sistema has de reemprendre sol·lucions desde zero.

Així que vaig a escriure el codi de red tal i com ha de ser. Aixó planteja un estudi interessant de quí es responsabilitza de que, com optimitzar la comunicació i altres coses que no son tan obvies com pareixen. Dona per a un post sucoset, que estic escrivint, pero no tinc el temps suficient per a acavar-lo hui, així que demà, si tot va be, parlaré largo y tendido sobre el tema.

dijous, 16 d’abril de 2009

Brand New Joguet!

Be, hui no hi ha update del Gauntlet, ja que he dedicat els ratos lliures que tenía a... comprar una PSP! 8D

Ja feia temps que li tenia ganes, sobre tot per a jugar a emuladors, al doom, al quake... Ho vaig parlar amb JDes i me va asesorar un poc. El cas es que ahir vaig anar a ModCenter, que allí te actualitzen el firmware i tot... i el tio me diu que les PSP que tenen no son piratejables. Jo ja sabia que la PSP 3000 no es podia encara, pero allí vaig vore PSP 2000...

Al arrivar a casa vaig investigar i resulta que segons el firmware que duen no es pot encara, per a ser exactes l'ultim firmware piratejable es el 3.95. Es pot saber, aproximadament, quin firmware te la consola mirant la etiqueta de la caixa. Si la lletra es menor que G, es pot piratejar. La G potser si o poster no, i més avant no es pot. Pareix que Sony, desde nadal o per ahí segons me va dir el de ModCenter, nomes serveix versions G o superior.

La veritat es que no tenia ganes de calfarme el cap, així que ja m'havia fet a la idea de esperar i comprar la GP2x Wiz. Pero mira, este matí, quan he anat al OpenCor a comprar les rosquilletes he vist que tenien PSPs. Tenien una 3000, una 2000 G i una 2000 que venia amb el Lego Indiana Jones que no es veïa la versió (al ser un pack, du una caixa recobrint la caixa de la consola i el joc).

He tornat al curro i he investigat, i després de vore varios casos que deien que eixe pack duia una versió F, he anat i l'he comprat. Efectivament, era una F amb firmware 3.90.

A hora de dinar he anat a dur la PSP a ModCenter per a que li canviaren el firmware. La veritat es que esperava que tindria que deixar-la un dia, o inclus una setmana... pero nomes entrar el tio me diu "vaya, has encontrado una F", ha tret una bateria gorda i una memory stick, a apretat dos botons, m'ha fet el ticket (30€ de piratejar, que li anem a fer), i pis pas, ja estava apanyadeta. Pos millor.

Al tornar he provat el Lego Indiana... La puta! Tots els UMDs tarden esta eternitat en carregar?? m'ha recordat a la época del spectrum. Després he provat el Quake i el Rise Of The Triad, tot va de boles.

Externament la esperava mes boniqueta, respecte als acavats. La pantalla pareix que estiga encastrada, i a les vores de la pantalla la pintura pareix que estiga un poc com a gotes, com mal pintada... pero be, després de vore els acavats de un iPhone o iPod Touch... :-)

Seguidament he vist que es pot desenvolupar amb SDL... així que en uns dies faré els primers experiments, i algún port de jailgame caurà.

Be, content amb la compra. Realment la vull per jugar en la sobretaula al sillo amb Mariola, i no tindre que marginarme al estudi si vull jugar (la DS no dona pa molt).

Ale, demà seguim programant.

dimecres, 15 d’abril de 2009

Cas d'estudi: Gauntlet - Part Va: Red

Hui he estat preparant el codi de red. Per a la comunicació per red vaig a usar SDL_net (per als interessats, s'instala igual que SDL_image o SDL_mixer, segons explique al primer tutorial).

En principi he decidit que el servidor no siga més que un distribuidor d'ordres entre jugadors. O siga, si el jugador 1 comença a caminar cap a la dreta, envia un missatge al servidor dient-ho, i este redistribueix el missatge als demes jugadors, que mouràn al jugador convenientment. Aquesta aproximació es simplista i perillosa, pero es un començament.

En general, amb aquesta aproximació tot el proces que hi ha al joc ha de ser determinista. O siga, res de coses aleatòries, perque si cada comp decideix donar una aleatorietat diferent, les diferents versions en cada comp faran el joc injugable. En el cas de que s'introduïren elements aleatoris, deuria haver un "generador de nombres aleatoris en red" o similar, o sino, que siga el servidor el que genere aquesta aleatorietat. A més, problemes de sincronització, on un jugador pot estar uns pixels més lluny en un comp que en altre, poden dur a inconsistències. I es que fa falta un àrbitre que prenga les decisions importants, com per exemple si una bala a tocat a un personatge.

Tot açò ens du a que el servidor tindrà que estar "jugant" la partida també, tenint la seua versió al igual que els demes jugadors, i si hi ha algún event important, serà el servidor el que avisarà, mentre que els jugadors mai prendràn decisions sobre eixes coses. Per exemple, si una bala colisiona amb un personatge, el comp jugador no dirà ni mu. Serà el servidor el que, quan detecte aquesta situació, enviarà un missatge de colisió entre la bala i el personatge. Pot donar casos raros en que una bala que clarament ha tocat a un jugador en un comp, passe de llarg perque en el servidor no l'ha tocat, per diferencies de sincronia, pero al menys tots els comps tenen la mateixa versió dels fets i no es desincronitzen.

De totes formes, com ja he dit, al principi el servidor serà un distribuidor d'ordres i au. Per a joc en red local deuria ser suficient, amb latencies menors de 1ms (ara mateix el bucle de programa procesa ordres, com a molt, cada 10ms).

El que segurament implementaré prompte es el "paquet de sincronia". Durant el PFC vaig descobrir que les latencies havien baixat dràsticament desde que el vaig començar. Al final, fent que el servidor fora un redistribuidor i au funcionava be el 99'9% del temps. L'unic problema era si algún paquet UDP es perdia pel camí (lo qual ocorria una vegada de cada 10000 en Internet, i fent el burro amb coses descarregant i tal fa forçar la red. No ho vaig poder reproduïr en red local). Obviament, si se perd un paquet, encara que siga cada 10000, ja estem fotuts.

El que vaig fer es enviar un paquet de sincronia cada x segons. Aquest paquet contenia les dades actuals del jugador (x, y, acció actual...). Així em servia de ping, per a estar segur de que el comp i el servidor seguien vius, i per a restablir la sincronia en el cas de que s'haguera perdut (el que feia era, quan arrivaba un paquet de estos, forçar la posició i tal de cada jugador).

De totes formes, aquesta solució no arregla el fet de que el paquetet que es perda just siga el que diu que he disparat, amb lo qual ningú s'enteraria de que hi ha una bala per ahí. Crec que per a solventar-ho vaig fer que tot paquet enviat esperara una resposta. Ara mateix no recorde si al final també numerava els paquets, per a estar segur de que no es perdia ninguno. He de repasar-me el PFC.

No he acavat el codi, ni del servidor ni del jugador, així que este capitol encara no està tancat.

dimarts, 14 d’abril de 2009

Dia raro

Hui he tingut el dia raro. Ahir vaig pensar en fer un mini-framework usant SDL per a pasar els antics jailgames de 8 bits de color més facilment, pel tema de les manipulacions de paleta que feiem, pero després d'un rato ho he tirat a la basura perque el SDL es subnormal i quan li canvies la paleta, en compte de canviar els color i au, li pega per també intentar adecuar l'imatge als nous colors. Que desastre!

Be, temps perdut. Després he estat un rato rumiant de fer un fast game que tenia en ment, pero ho deixe per a altre dia.

Després he mirat de fer algo del cas d'estudi. El cap de setmana se me va ocorrer un jailgame que fer amb eixe motor, així que prepararé els sprites per a tal joc. Ja parlaré de ell. No importa, no tinc grafics ni ripejats ni fets per als sprites, així que he pintat dos boles rotjes en la pantalla i he fet unes proves de sprites. Tot molt be i com esperava, excepte que el que vaig comentar del mapa te un error:

Quan es calcula el punt mitg, després se li restava la meitat del espai visible. Pos be, encara que l'espai visible siga 192 pixels, en realitat a mi m'interessa un tile menys, sino el sprite s'en eix un tile per fora de la pantalla, perque el punt (0,0) del sprite es el que està en la coordenada 192, deixant la resta del sprite fora (pasa igual que amb el cursor, si vos fixeu en les vores de baix i de la dreta s'en eix). El que he fet es restar la meitat de l'espai visible menys un tile, o siga: 192-16 = 176 / 2 = 88. Res, per a que quede per al record.

Ah, i se m'oblidà dir-ho ahir. He afegit un tutorial més de SDL als tutorials del nostre wiki. Amb aquest tutorial ja tindreu un projecte buit per a començar un jailgame. Amb eixe projecte buit, per exemple, ja podrieu compilar el Arounders.

A vore si demà avance més...

dissabte, 11 d’abril de 2009

Cas d'estudi: Gauntlet - Part IV: El mapa

Per fí anem a escriure codi del joc!

Comencem pel mapa. Per a gestionar el mapa he creat una clase LevelProcesor que s'encarregarà de carregar i pintar el mapa, així com de respondre als personatges que hi ha en cert tile.

El primer que vaig a fer es que es pinte el mapa que havem creat amb l'editor. Per a tal cosa, he ficat el arxiu del mapa dins un arxiu de recursos com en l'Arounders. Per a obtindre'l faig una cridada a GetBufferFromResource, de la API de lectura/escritura que tinc, que me tornarà un punter a un array de char. Eixe array el procese ficant el seu contingut dins de l'array que manté el mapa de blocs:

void LevelProcesor::LoadLevel(int level) {
int tamany = 0;
char *buffer = GetBufferFromResource("prova.lev", &tamany);
int contador = 3;

for (int y=0; y<32; y++) {
for (int x=0; x<32; x++) {
mapBlock[y][x] = buffer[contador];
contador++;
}
}
UpdateMapVis();
}

Com podeu vore, fique el contador a 3, per a botar-me els primers 3 bytes, que contenen el nombre de versió, i els dos bytes de tilesSet i color, que per ara no mire. També cride al mètode que actualitza el mapa visible.

A partir d'ara, per a parlar del mapa intern diré el mapBlock, mentre que per a parlar del mapa de tiles visibles diré el mapVis.

void LevelProcesor::UpdateMapVis() {
int tile = 0;

for (int y=0; y<32; y++) {
for (int x=0; x<32; x++) {

if (mapBlock[y][x] == 0) {
tile = 16;
if (x - 1 >= 0 && mapBlock[y][x-1] == 1) tile += 1;
if (x - 1 >= 0 && y + 1 <= 31 && mapBlock[y+1][x-1] == 1) tile += 2;
if (y + 1 <= 31 && mapBlock[y+1][x] == 1) tile += 4;
} else if (mapBlock[y][x] == 1) {
tile = 0;
if (y - 1 >= 0 && mapBlock[y-1][x] == 1) tile += 1;
if (x + 1 <= 31 && mapBlock[y][x+1] == 1) tile += 2;
if (y + 1 <= 31 && mapBlock[y+1][x] == 1) tile += 4;
if (x - 1 >= 0 && mapBlock[y][x-1] == 1) tile += 8;
}
mapVis[y][x] = tile;
}
}
}

El calcul de quin tile li toca a una paret es prou simple. El que ens importa es si té alguna paret a algún costat en horitzontal o en diagonal, així que asigne potències de dos a cada costat i el que faig es sumarles segons quines parets trobe. Aixó ens dona 16 combinacions, que ficaré en el bitmap de tiles en ordre:


Amb el piso es similar, però com el que canvia es si té alguna paret als costats en que fan sombra, nomes m'importen els costat de l'esquerra, baix, i esquerra-baix en diagonal, donant-me un total de 8 combinacions que també ficaré en ordre en el mapa de tiles:


Mmm, me pareix que algú vol un biberó. Ara vinc...


Ale seguim. Per a pintar el mapa, bàsicament faré un bucle pintant 13 tiles a partir d'un offset:


for (int j=0; j<=12; j++) {
for (int i=0; i<=12; i++) {
tiles->Draw((i<<4)-(offsetX%16),
4+(j<<4)-(offsetY%16),
16,
16,
(mapVis[j+(offsetY>>4)][i+(offsetX>>4)]%16)<<4,
(mapVis[j+(offsetY>>4)][i+(offsetX>>4)]>>4)<<4,
16,
16,
0,
0,
255,
actualColorSchemes[mapVis[j+(offsetY>>4)][i+(offsetX>>4)]>>4].red,
actualColorSchemes[mapVis[j+(offsetY>>4)][i+(offsetX>>4)]>>4].green,
actualColorSchemes[mapVis[j+(offsetY>>4)][i+(offsetX>>4)]>>4].blue
);
}
}

Per recordar-ho: els 4 primers paràmetres son la X, Y, ample i alt del tile en el destí, els 4 següents el mateix pero en l'origen. Els següents son l'angle de rotació, si fa espill i el canal alfa.

Els tres últims paràmetres son el RGB amb que anem a tintar el tile. En el bmp he deixat els tiles en blanc i negre, així els puc aplicar un tint i tinc més varietat de tiles canviant-los el color. Per ara he deixat 8 colors: roig, verd, blau, groc, taronga, morat, gris oscur i gris clar.


Tornant al pintat del mapa, no ens interesa pasar-li uns offsets i au. El que ens interessa es pasar-li entre una i quatre coordenades (x,y) (una per jugador) i que la pantalla es centre en eixes coordenades.

Per a aconseguir-ho, buscarem la x major, la x menor la y major i la y menor. El punt central serà (per a la X, la Y es igual):

migX = ((maxX-minX)/2)+minX

Al punt mig, restant-li la meitat dels pixels que ocupa la pantalla visible (32 tiles * 16 pixels = 192 pixels / 2 = 96 pixels) tindrem el punt des d'on començar a pintar. Abans de pintar, restringirem que eixe punt estiga dins dels límits (si la X calculada es menor que zero, la ficarem a zero, etc...).

Una aclaració, per si algú ja no recorda el tema dels scrolls. La pantalla visible son 12 tiles, pero en pinte un més perque durant la transició de un tile a altre, en pantalla hi ha 11 tiles sencers, i el primer i últim a meitant. Per tant, eixe tile 13.

Per últim, ens queda retallar eixe tile, que es pinta sencer, pero nomes en volem un trocet. Si el scroll fora a pantalla sencera no hi hauria problema, ja que la part de tiles que no volem estaria fora de la pantalla, pero la pantalla visible es de 192x192.



Aixó ens donarà 4 pixels per dalt i per baix a retallar, i 16 pixels per la dreta (per l'esquerra estem a ras de pantalla). Per a cobrir estos trocets no desitjats pinte damunt d'ells un poligon negre simple (un per cada costat).


Be, el següent es ficar els personatges en marxa. Vaig a rippejar els sprites i a la feina. Com a resenya, dir que m'ha costat mes del doble escriure el post que la feina que explique :-P. Ale, un shot, que quasi se m'oblida:

dijous, 9 d’abril de 2009

Cas d'estudi: Gauntlet - Part III: El editor

Després d'una nit en la que he pogut dormir unes quantes hores seguides, hui m'he alçat reconfortat i m'he ficat a la faena.

He començat l'editor de mapes. Per ara nomes pot ficar parets o llevar-les. Aniré completant-lo conforme el joc ho requereixca.


En principi, parlar del format del mapa. El mapa en sí es un simple array de 32x32 bytes, en el qual, ara mateix, nomes pots trobar zeros (buit) o unos (paret). Aquest es el mapa que m'interesa per a procesar colisions i tota la peixca interna.

No obstant, hi ha un segon mapa que es el que realment es pinta ¿perqué? Si vos fixeu en els tiles de les parets del Gauntlet no son tots iguals:


Com podeu vore, depenent de si un bloc de paret te un altre bloc a algún costat, es pinta de una forma o altra. Es més, els tiles del piso tampoc son iguals: Si tenen una paret prop potser tinguen sombra. Aixó ens dona un total de 16 posibilitats de paret (en la versió arcade en son alguna més al ficar més sombretes xules, pero per ara ho ignorarem) i 8 posibilitats per al piso (2 de les quals son iguals, pero també ho ignorarem)

Així pues, el que faig es, a partir del mapa de parets i buits, monte altre mapa en el que calcule, per a cada bloc, quin tile li toca mostrar. Aquest calcul el faig al principi de carregar i mostrar el mapa, i després vaig actualitzant nomes els tiles que canvien. En l'editor els tiles canvien molt a sovint, pero en el joc hi ha pocs moments en que canvien (obrir portes, que encara no les havem tractat, i obrir "parets trampa", que tampoc les tractem encara).

La veritat es que en principi no volia fer-ho per al editor, que no passa res si es veu mal, pero al final ho he fet tant per practicar-ho com perque sempre mola més vore-ho tot sucoset ;-D

Altra questió es el format dels mapes. Com segurament vaja canviant durant el desenvolupament, he fet que el primer byte del mapa indique la versió. Així, l'editor el primer que fa es llegir este byte i redirigir a la rutina de càrrega de la versió del mapa corresponent. Ho he fet així per no perdre mapes de versions anteriors. Ara no importa molt, pero si cap al final, amb uns quants mapes fets, he de canviar el format, pot ser un fer la mà refer els mapes.

Per ara, els dos següents bytes estàn a zero, pero representaràn el tileset i color de les parets i el piso. I després ja van 32x32 bytes que representen cada bloc del mapa (en format simple, el calcul de tiles que he comentat avans es torna a fer desde el joc, me pareix una opció més segura i, a més, el precalcul de tiles es ràpid i es fa nomes una vegada). Els bloc estàn guardats en format de lectura occidental, d'esquerra a dreta i dalt a baix. O siga: Y=0, totes les X, Y=1, totes les X...).

Be, en el pròxim capitol ja començarem a escriure codi del propi joc. Començarem per implementar el pintat del mapa, el scroll i el centrat del mapa en varios punts, com fa el Gauntlet per a mantindre a tots els personatges en pantalla. Començare sobre la base del Patman en el que respecta a estructura del joc, pintant, sò i teclat.

Volia anar ficant a disposició de tots el codi font conforme es va escrivint, i el subversion del Google Code es perfecte per a tal cosa (on està el Arounders), però necessite un nom per al projecte, i ficar-li Gauntlet no em pareix apropiat. ¿Algú me proporciona un nom per a aquest Gauntlet Jailer?

PD: Ah, i ficaré també els executables i codi dels programetes perifèrics que vaja fent, com l'editor de mapes, encara que estos sense control de codi font.

dimecres, 8 d’abril de 2009

Estic malet...

Aixó, que el dilluns ja em trobava fatal, ahir no vaig eixir del llit, i hui encara no estic massa be. Supose que no dormir res de bo (coses del nano) junt amb un constipat mal curat m'han deixat fet pols.

Crec que el tema de atascar-me amb el patman i tal també te que vore amb dur messos sense dormir com deu mana.

dilluns, 6 d’abril de 2009

Cas d'estudi: Gauntlet - Part II: Continguts

Vaig a parlar de qué trobarem en el joc. Està basat en el Gauntlet, però no te perquè estar tot lo del Gauntlet ni te perquè estar fet de la mateixa forma.

Mapa
El mapa basic estarà format per:

  • Buits: Obviament, per ací es per on es pot caminar sempre.

  • Parets: Les parets son tot el contrari als buits.

  • Portes: Les portes son com parets fins que colisionem amb una portant una clau.

  • Parets "borrables": Son com les parets, pero al xafar una "trampa" desapareixen. Podrà haver fins a tres parelles de trampes i grups de parets borrables.

  • Parets trencables: Son parets que després de pegar-li un parell de castanyes desapareixen.

  • Entrada: Nomes hi ha una i es on apareixen els herois al començar un mapa.

  • Eixides: Al xafarles pasarem de pantalla. No vaig a implementar les eixides a pantalles avançades.

  • Teletransports: Al xafarlos anirem al altre teletransport més proper (i que estiga en pantalla) que hi haja.

  • Trampes: Les trampes son taulells, que brillaràn o el que siga, que al xafarlos farán desapareixer les parets asignades a ells.



Enemics
Al mapa també podem trobar enemics i generadors d'enemics. Cada tipus d'enemic pot apareixer en tres variants diferents, sent cada variant mes forta que l'anterior. Hi haurà un generador per a cada tipus d'enemic i per a cada variant del mateix enemic.

  • Fantasma

  • Grunt

  • Dimoni

  • Hechicero

  • Llançadors



A més d'aquestos, també estará la mort, que no te diferents nivells ni te generador. No vaig a implementar el lladre.

Objectes
Per últim, podem trobar diferents coses que podem arreplegar:

  • Clau: Si havem agafat una clau, podrem obrir una porta al tocarla

  • Tresor: Ens donarà punts

  • Pocio Blava: Si després d'arreplegar-la la llançem farem pupa als malos. També podem disparar-li per a trencar-la, pero farà menys efecte.

  • Pocio Roja: Igual que la blava, pero no es pot trencar.

  • Menjar: Ens torna punts de vida al arreplegar-lo. Hi ha una variant destructible i altra indestructible.

  • Pocions Extra: Al arreplegar-les ens upgradaràn alguna de les següent qualitats: Armadura, Màgia, Poder de dispar, velocitat de dispar, velocitat al caminar i poder cos a cos. Per lo demés es comportaràn exàctament igual que una poció blava.




Tot açò ens dona un total de 56 posibles "tiles" a colocar en el mapa. Després, al joc, alguns es transformaràn en tiles que formaràn el mapa i altres en sprites. De fet, les parets es transformaràn en un tile més especific, per a fer la formeta segons cap on miren i tal, pero això ja ho vorem més avant.

A part, cada mapa tindrà, com a propietats, el tileset usat per a les parets, el tileset usat per al piso, el color de les parets i el color del piso: hi haurà diferents tilesets, i per a cada tileset se li podrà especificar una gama de colors.

Cada mapa estarà format per 32x32 tiles, dels quals es vorà una finestra de 12x12 tiles. Cada tile serà de 16x16 pixels.

Açò ja anirà canviant segons vaja trobant coses que falten o coses que me digau vosaltres. Supose que mes avant afegiré coses com el collar de invisibilitat, invencibilitat, o coses de eixes. Amb la informació que tenim ja podem fer un editor rapidet.

divendres, 3 d’abril de 2009

Cas d'estudi: Gauntlet - Part I: Introducció

Be, per a despejar-me un poc vaig a començar un cas d'estudi que desenvoluparé detalladament al llarg d'estos dies. He triat el Gauntlet, ja que desde l'altre dia que el Gamer ho va comentar m'entraren ganueles.

L'objectiu es desenvolupar el Gauntlet. No vaig a calfar-me el cap i vaig a usar els gràfics i la mecànica del joc original. Si més avant es vol fer un JailGame amb història i gràfics propis, que algú propose algo.

Crec que tots coneixeu el Gauntlet, així que no vaig a comentar la mecànica del joc. El que sí comente es que ha de poderse jugar offline, like el joc original, i online, a traves d'un servidor dedicat. En principi no em planteje que el servidor puga ser un dels jugadors.

Per a aconseguir aquesta dualitat desenvoluparé unes classes proxy que em premeten interactuar amb el joc independentment de que les ordres arriven des del teclat o desde la xarxa. Com a extra, desenvoluparé altra classe proxy que permeta que el joc jugue sol amb una serie d'ordres pregrabades, like el mode demo de les recreatives. Açò implica que tindré que fer una classe sniffer que grave les ordres entre el proxy i els elements del joc, encara que es probable que, en compte de crear una classe a propòsit, clave la lògica dins la clase proxy base, de la que hereten les demés.

El joc permetrà dur fins a 4 personatges. Vaig a implementar personatges, enemics, items, etc... segons aquesta documentació. De totes formes, tampoc es l'objectiu calcar exàctament el comportament del joc original.

Usaré els gràfics del Gauntlet 2 per a PC, que puc ficar-lo al DosBox per a traure, facilment, tiles i sprites.


Ale, crec que ja no hem queda res que introduïr. Vaig a passar més temps escrivint ací que escrivint codi, així que la visibilitat del projecte serà quasi total. Mentres dure el cas d'estudi hi haurà dies que escriga varies parts, i si se administrarme be no deuria haver dia sense post. Aixó si, recordar que el cap de setmana sempre estic liat i se me fa dificil escriure, així que no promet res.

dijous, 2 d’abril de 2009

Que li peten!!!

Ie, no comprenc com se m'està resistint la merda de codi este. La funció de reordenació nova te polls raros de nou. Com ja estic prou cremat, crec que me fa falta donar-me un descas de Patman.


Per tant, es queda aparcat uns dies i aprofite per a tirar avant el Bryndiana. Com vaig dir en un post anterior, ara seràn tres jocs, i vaig a començar pel primer. He pensat que siga tipus Wizards & Warriors III respecte a estructura del joc. De totes formes, encara no ho tinc clar del tot. Si algú te alguna proposta...

El que sí tinc clar es alguns conceptes. Pantalla amb scroll amb posibilitat de anar amunt, avall, esquerra i dreta, amb llocs on es pot entrar, amb tendes, amb diferents zones a les que no es pot accedir fins no aconseguir alguna cosa, amb prou enemics pel camí, no dificils de matar pero que si estiguen donant pel cul per a no avorrir...

Portes i tamany d'habitacions

Ahir no vaig poder escriure abans d'anar-me'n a casa, el blogger este no anava be, i en casa ja va ser impossible ficar-se cara al comp.

Vaig estar implementant els tamanys variables d'habitació, així com les portes.


Cada eix pot ser de 8 tiles, 6, 4 o 2, excepte l'altura, que sempre es de 4 tiles.


Encara que la lògica de les portes ja està pràcticament implementada, no es pot vore res perque encara no he fet gràfics per a elles, a part de tampoc tindre habitacions per les que caminar (l'habitació usada fins ara estava montada a mà desde el codi.

Respecte a les habitacions, funcionaràn de la següent forma: Cada habitació tindrà sis referències a portes, una per cada costat (est, oest, nord, sud, dalt i baix. Si està a -1 no hi ha porta, en altre cas durà a l'habitació amb el número indicat. A més, les portes est, oest, nord i sud tenen altura (0, 1, 2 o 3). Cada habitació també té un flag que especifica si el piso mata al tocarlo.
respecte als gràfics, cada habitació nomes te una referència a un "tileset".

Cada tileset especifica:
- El tile del piso
- Els tiles de les parets per a cada tamany de paret i si te porta o no
- Els tiles de les portes

Es un sistema que restringeix més la varietat de gràfics, pero es que quan més genèric tot més se perd uno fent mil coses. Si ho tinc més arreplegadet me centre més i no tarde una eternitat (o no l'acave). Per lo demés, també usarà menys memòria per a guardar els mapes.

Hui intentaré dedicar-me a fer grafics i l'editor.

dimecres, 1 d’abril de 2009

Patman movent caixes

El video que volia pujar ahir, gracies a les recomanacions del JailDesigner:

video


Al ser de 320x200 i redimensionarlo a 640x480 se veu estirat, pero be.

Per cert, el que es veu baix de Patman ho he deixat per a tindre una referència exacta de en quin tile està.