dijous, 7 de maig de 2009

API per a Jailgames

Vaig a presentar un poc la API que vaig a usar durant el cas d'estudi. Està composta de 6 moduls:

- JGame: S'encarrega de les coses genèriques.
- JDraw: S'encarrega de la part gràfica.
- JInput: S'encarrega dels dispositius d'entrada.
- JSound: S'encarrega del só i la música.
- JFile: S'encarrega de la càrrega de arxius encapsulats.
- JNnet: S'encarrega de la comunicació per red.

Per ara inclouré els 5 primers. jnet el deixe per a mes avant.

JGame

void JG_Init(char *title);
- Inicialitza tot el sistema. S'ha de cridar abans de res. El paràmetre que rep es el titol que tindrà l'aplicació en la barra de titol.

void JG_Finalize();
- Finalitza el sistema. S'ha de cridar al final de tot.

void JG_QuitSignal();
- Al cridar a aquesta funció marquem la senyal de que volem eixir de la aplicació. en realitat no fa res més que ficar un booleà a true. El criden algunes funcions internes per a avisar-nos de que ha ocorregut algún event d'eixida de l'aplicació. Si quan decidim que volem eixir de la aplicació l'usem, podrem gestionar-ho tot des del mateix lloc.

bool JG_Quitting();
- Aquesta funció ens tornarà true si la senyal anterior s'ha activat. Com ja he dit, podem activar-la nosaltres o potser s'ha activat internament, per exemple, quan pulsem l'aspa de tancar la finestra. Si no la tenim en compte i la ignorem, no es podrà tancar l'aplicació de les formes normals en que se tanca una aplicació.


JDraw

void JD_Init(int screenWidth, int screenHeight, bool doubleSize);
- Incialitza el sistema gràfic, amb la resolució indicada. Si doubleSize es true la finestra serà el doble de gràn. El mode de pantalla completa encara no està implementat. El ser una finestra, es pot ficar la resolució que es vullga.

void JD_ClearScreen(Uint32 color);
- Ompli la pantalla del color especificat (format de color: 0xRRGGBB)

JD_Surface *JD_LoadSurface(char *file, bool doColorKey = false);
- Carrega una imatge en una superficie. Les superficies son com les pantalles virtuals de antaño. Si s'especifica true per a doColorKey, els pixels de color 0xFF00FF seràn transparents. Més avant faré que el color transparent siga configurable.

void JD_Blit(int x, int y, JD_Surface *surface);
- Pinta la superficie "surface" en la posició (x,y) de la pantalla.

void JD_Blit(int x, int y, JD_Surface *surface, int sx, int sy, int sw, int sh);
- Pinta en la posició (x,y) de la pantalla, el rectangle (sx, sy, sw, sh) de la superficie "surface".

void JD_BlitToSurface(int x, int y, JD_Surface *surface, int sx, int sy, int sw, int sh, JD_Surface *dest);
- Igual que la anterior, pero en compte de pintar a pantalla, pinta sobre altra superficie "dest".

void JD_Flip();
- Fa el tipic flip per a que es mostre el que havem estat fent.

void JD_FreeSurface(JD_Surface *surface);
- Quan hajam acavat amb una superficie tenim que alliberar la memòria que havia reservat o es quedaràn "memory leaks".

Uint32 JD_GetPixel( JD_Surface *surface, int x, int y );
- Obtindre el pixel (x,y) de la superficie "surface".

void JD_PutPixel( JD_Surface *surface, int x, int y, Uint32 pixel );
- Escriure el pixel (x,y) del color "pixel".

void JD_FadeOut();
- Fa un fade a negre de forma síncrona. O siga, no es torna el control a la aplicació fins que no acava el fade.

void JD_FadeIn();
- Fa un fade desde negre. Recordeu pintar primer algo o no es farà res.


JInput
Per ara aquesta API la he deixada molt coixa. Més avant l'arreglaré bonica i amb soport per a ratolí i pad.

void JI_Update();
- Actualitza l'estat dels dispositius d'entrada. S'ha de cridar a cada pas del bucle de programa.

bool JI_KeyPressed(int key);
- Comprova si s'ha polsat determinada tecla.


JSound

bool JS_Init();
- Inicialitza el sistema de só.

void JS_LoadMusic(char *musicFilename);
- Carrega una cançò.

void JS_SetMusicVolume(int volume);
- Fixa el volum de la cançò (128 màxim)

void JS_PlayMusic(int loops);
- Fa que sone la música. Si loops = -1, sona infinitament. Si loops = 0 sona una vegada, si loops = 1 sona dos vegades, etc...

void JS_PauseMusic();
- Pausa la cançò.

void JS_FadeOutMusic();
- Para la cançò baixant progresivament el volum.

bool JS_MusicPlaying();
- Si la música està sonant, torna true.

JS_Sound *JS_LoadSound(char *soundFilename);
- Carrega un só.

void JS_SetSoundVolume(JS_Sound *sound, int volume);
- Fixa el volum del só.

void JS_PlaySound(JS_Sound *sound);
- Fa que sone el só.

void JS_FreeSound(JS_Sound *sound);
- Allibera la memòria ocupada per un só.

void JS_Finalize();
- Tanca el sistema de só.


JFile

void JF_SetResourceFile(char *p_resourceFileName);
- Fixa el arxiu paquet des del que se tenen que agafar els arxius. Per defecte es "data.jrf".

char *JF_GetBufferFromResource(char *resourcename, int *filesize);
- Obté un arxiu del arxiu paquet. Torna un punter a array de char. A més en el paràmetre d'entrada/eixida "filesize" escriu el tamany d'aquest array.


Exemple
Conforme anem avançant en el cas d'estudi anirem vegent-ho quasi tot, pero vaig a escriure un xicotet programeta d'exemple. Com podeu vore per la API, no estic usant orientació a objectes, i no la vaig a usar durant el cas d'estudi, per fer-ho tot el més similar als JailGames de antaño.

El que anem a fer es carregar un gràfic que ficarem de fondo, altre gràfic que serà un set de tiles, i en pintarem un en pantalla, un mp3 de música que deixarem sonant de fondo, i un WAV que sonarà quan pulsem la tecla espai.


#include "jgame.h"
#include "jdraw.h"
#include "jinput.h"
#include "jsound.h"

Incloguem les unitats que anem a usar.


int main( int argc, char* args[] ) {
JG_Init("PROVA");
JD_Init(320, 200, false);
JS_Init();

Primer inicialitzem els sitemes. El general, el de gràfics i el de só.


JD_Surface *fondo = JD_LoadSurface("jailgames.gif");
JD_Surface *tiles = JD_LoadSurface("tiles.gif");

Carreguem els gràfics necessaris.


JS_LoadMusic("musica.mp3");
JS_Sound *bomba = JS_LoadSound("chainsaw.wav");
JS_SetSoundVolume(bomba, 4);

JS_PlayMusic(-1);

Carreguem la música, el só, i li fiquem volum al só (no se perqué s'escolta altissim, per això l'he ficat a 4). Per últim, fem que sone la música indefinidament.


JD_Blit(0, 0, fondo);
JD_Blit(0, 0, tiles, 16, 32, 16, 16);
JD_FadeIn();

Pintem el fondo i el tile, i aleshores fem el fadein. Si no haguerem pintat res, no podriem fer fade de res.


while (!JG_Quitting()) {

Entrem en el bucle de programa. S'executarà fins que arrive una senyal de tancar.


JD_Blit(0, 0, fondo);
JD_Blit(0, 0, tiles, 16, 32, 16, 16);
JD_Flip();

Pintem el fondo i el tile i fem flip, ara ja dins del bucle.


JI_Update();

if (JI_KeyPressed(SDLK_SPACE)) {
JS_PlaySound(bomba);
}

if (JI_KeyPressed(SDLK_ESCAPE)) {
JG_QuitSignal();
}

Actualitzem els dispositius d'entrada i aleshores comprovem si s'ha pulsat la tecla espai (si s'ha pulsat, fem sonar el só), i la tecla ESC (si s'ha pulsat enviem senyal d'eixir de la aplicació).


}
JS_FadeOutMusic();
JD_FadeOut();

Quan eixim del bucle fem un fadeout de la pantalla i de la música.


while( JS_MusicPlaying() ) { };

Aquest bucle farà que l'execució es pare fins que deixe de sonar la música.


JS_FreeSound(bomba);
JD_FreeSurface(tiles);
JD_FreeSurface(fondo);

Alliberem la memòria reservada per els gràfics i el só. La música la gestiona la unitat així que no ens preocupem.


JS_Finalize();
JG_Finalize();

return 0;
}

Finalitzem els sitemes. JDraw, per ara, no requereix finalització.

Ale, adjunte el códi font per si voleu començar a trastejar. El projecte es diu SuperMarioBros, perque es la plantilla que ja tenia preparada per al cas d'estudi.

També adjunte el programa ResPack, una xicoteta aplicació que vaig fer per a agafar tots els arxius de un directori i ficarlos en un JRF (Jailgames Resource File). Totes les funcions de la API lligen de un JRF, mai directament de disc, així que si voleu modificar algún arxiu tindreu que regenerar el JRF que adjunte, que realment conté els arxius que teniu al directori "recursos".

Joder, que post més llarg. Si algú te dubtes que escriga un comentari, que ja no vull allargar açò més.

2 comentaris:

  1. Ara si que si, a vore si entre hui i demà ho deixe tot preparaet per a anar compilant mini-exemples.

    A mi m'agradaria anar fent coses de prova abans de clavarse en un joc.

    Pa començar molaria fer la tipica pilota rebotadora i anar avançant sobre ella. Animarla, mouere-la amb el teclat .. aixi poc a poc anar veient el esquelet d'aquest tipus de programes.

    Que jo no programe res desde fa anys.

    ResponElimina
  2. Mola mola. En el següent post tens un esboç d'estructura de joc. A més, també està la API actualitzada.

    ResponElimina