/* Nived: l'éditeur de niveaux de BomberInstinct */ #include #include #include #include #include "macros.h" #define MAX_NPERSO 20 #include "sprites.h" /*--Structures--*/ typedef struct { int x; int y; }Coord; typedef struct { int type; Sprite *elem; int anim; int frame; int params[260]; /* Structure simplifiée par rapport au jeu */ int nparams; int sol; int fixe; }Case; const char legende[]="LÉGENDE :" "_ sol" "+ mur" "# bloc" "T[case] téléportation[case de 0 à 240]" "O[case] bouton[idem]" ">[sens] flèche[0:haut, 1:bas, 2:gauche, 3:droite]" "=[direction] tunnel[0:, 1:<^>, 2:^v>, 3:<^v, 4:<^, 5:^>, 6:, 8:^v, 9:<>, 10:<^v>]" "* fontaine(régénération)\n"; int NB_PERSO, VITESSE, REGEN, LFLAMMES, NBOMBES, REBOURS, BONUSFREQ; int pleinecran; int danslemenu=0; Uint32 flags; char repertoire[256]; char prefixeniv[256], prefixespr[256]; char niv[256]; Case pl[18][15]; Coord persopos[8]; Coord actif; Sprite *nived; Sprite *elemliste[50]; Sprite *nb[8]; char graphtype[256]; int decl; SDL_Rect tout, plateau, recdroite; SDL_Surface *ecran; Uint8 *clavier; int compteur; int encore; Case elemactif; int *paramsbuf, nparamsbuf; int dx[4]={ 0, 0,-1, 1}; int dy[4]={-1, 1, 0, 0}; int aleat(int max); void erreur(char message[200], char param[20]); void animsplus(Sprite *sprite, int anim, int vitesse, int duree, int x, int y); void rscaseplus(int x, int y); void rdplateau(void); void initliste(void); void erreur(char message[200], char param[20]) { printf ("\nErreur :\n%s", message); if (param) printf(" : %s", param); printf (".\n%s\n", SDL_GetError()); exit(0); } /*--Initialiser l'écran--*/ int init_sdl(void) { Uint32 params; int ok; char titre[256]; flags=SDL_HWSURFACE|SDL_HWPALETTE; params = pleinecran ? flags|SDL_FULLSCREEN : flags; if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { erreur("Impossible d'initialiser SDL", NULL); } sprintf(titre, "Nived - l'éditeur de niveaux de BomberInstinct - %s - v1.0", niv); SDL_WM_SetCaption(titre, "Nived"); ok=SDL_VideoModeOK(640, 480, 8, params); if (ok==0) erreur("Le mode vidéo requis n'est pas disponible (640x480)", NULL); ecran = SDL_SetVideoMode(640, 480, 8, params); if ( ecran == NULL ) { erreur("Impossible d'initialiser l'écran en mode 640*480 8 bits", NULL); return 1; } atexit(SDL_Quit); SDL_EnableKeyRepeat(0,0); SDL_ShowCursor(1); return 0; } int aleat(int max) { int num; num=(int)(max * ((float)rand()) / ((float)RAND_MAX) ); return num; } void passenpleinecran() { int i, ncoul; SDL_Surface *sauvegarde; SDL_Color *pal; ncoul=ecran->format->palette->ncolors; pal=(SDL_Color *)calloc(ncoul, sizeof(SDL_Color)); for (i=0; iformat->palette->colors[i].r; pal[i].g=ecran->format->palette->colors[i].g; pal[i].b=ecran->format->palette->colors[i].b; } sauvegarde=SDL_DisplayFormat(ecran); SDL_FreeSurface(ecran); if ((ecran->flags & SDL_FULLSCREEN)==SDL_FULLSCREEN) ecran = SDL_SetVideoMode(640, 480, 8, SDL_HWSURFACE|SDL_HWPALETTE); else ecran = SDL_SetVideoMode(640, 480, 8, SDL_HWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN); SDL_SetColors(ecran, pal, 0, ncoul); free(pal); SDL_BlitSurface(sauvegarde, NULL, ecran, NULL); SDL_Flip(ecran); SDL_FreeSurface(sauvegarde); return; } int filtr_evt(const SDL_Event *evt) { if (evt->type == SDL_QUIT) exit(0); if (evt->type == SDL_KEYDOWN) { if (evt->key.keysym.sym==SDLK_c) if (evt->key.keysym.mod==KMOD_LCTRL) exit(0); if (evt->key.keysym.sym==SDLK_F10) exit(0); if (evt->key.keysym.sym==SDLK_F1) passenpleinecran(); } return 1; } void videcran(void) { SDL_FillRect(ecran, &tout, 0); SDL_Flip(ecran); return; } /*--Redessine une case (x, y) du plateau--*/ void dessinecase(int x, int y) { int xx=x*32; if (x>15) xx+=32; if (pl[x][y].sol) blitsprit(sol, 0, 0, xx, y*32); blitsprit(pl[x][y].elem, pl[x][y].anim, pl[x][y].frame, xx, y*32); if (pl[x][y].fixe==1) blitsprit(nived, 0, 0, xx, y*32); return; } void rdicones(void) { int x, y; for (y=0; y<15; y++) for (x=16; x<18; x++) dessinecase(x, y); blitsprit(nb[0], 1, 0, 17*32, 14*32); blitsprit(nived, 0, 3, 18*32, 14*32); return; } void rdplateau(void) { int x, y; for (y=0; y<15; y++) for (x=0; x<16; x++) dessinecase(x, y); rdicones(); return; } void chargeniv(FILE *fich, int tete) { int x, y, i; char niv, c; if (tete) { fscanf(fich, "REGEN=%i\n", ®EN); fscanf(fich, "BONUSFREQ=%i\n", &BONUSFREQ); fscanf(fich, "NBOMBES=%i\n", &NBOMBES); fscanf(fich, "REBOURS=%i\n", &REBOURS); for (i=0; i<8; i++) { fscanf(fich, "perso[%*i]:(%i,%i)\n", &x, &y); persopos[i].x=x; persopos[i].y=y; } } do fread(&niv, 1, 1, fich); while (niv!='{'); fread(&c, 1, 1, fich); for(y=0; y<15; y++) for(x=0; x<16; x++) { int params[260]; int nparams=0; niv=c; while (niv=='\n' || niv==' ') fread(&niv, 1, 1, fich); fread(&c, 1, 1, fich); while (c=='[') { fscanf(fich, "%i]", ¶ms[nparams]); nparams++; fread(&c, 1, 1, fich); } pl[x][y].elem=sol; pl[x][y].type=LIBRE; pl[x][y].anim=0; pl[x][y].frame=0; pl[x][y].sol=0; pl[x][y].fixe=0; for (i=0; i0.9*RAND_MAX) pl[x][y].anim = 1; pl[x][y].frame = aleat(sol->anims[pl[x][y].anim]->nframes); } else { pl[x][y].anim=2; pl[x][y].frame=params[0]; pl[x][y].fixe=1; } }break; case '#' : { pl[x][y].elem=bloc; pl[x][y].type=DESTRUCTIBLE; pl[x][y].anim=0; pl[x][y].sol=1; if (!nparams) pl[x][y].frame=aleat( bloc->anims[0]->nframes); else { pl[x][y].frame=params[0]; pl[x][y].fixe=1;} }break; case '+' : { pl[x][y].elem=mur; pl[x][y].type=INDESTRUCTIBLE; if (!nparams) pl[x][y].frame=aleat( mur->anims[0]->nframes); else { pl[x][y].frame=params[0]; pl[x][y].fixe=1;} }break; case '=' : { pl[x][y].elem=tunnel; pl[x][y].type=TUNNEL; pl[x][y].frame=params[0]; pl[x][y].fixe=-1; }break; case '>' : { pl[x][y].type=SENSUNIQUE; pl[x][y].elem=fleche; pl[x][y].anim=params[0]; pl[x][y].sol=1; pl[x][y].fixe=-1; }break; case 'T' : { pl[x][y].type=EVENEMENT; pl[x][y].sol=1; pl[x][y].elem=teleport; pl[x][y].fixe=-1; }break; case 'O' : { pl[x][y].elem=bouton; pl[x][y].sol=1; pl[x][y].type=EVENEMENT; pl[x][y].fixe=-1; }break; case '*' : { pl[x][y].type=EVENEMENT; pl[x][y].sol=1; pl[x][y].elem=fontaine; pl[x][y].fixe=-1; }break; default : { erreur("Ce niveau contient des éléments spéciaux." "Vous ne pouvez pas l'éditer avec nived", NULL); }break; } } do fread(&niv, 1, 1, fich); while (niv!='}'); return; } void sauveniv(char *nom) { int x, y, i; int ncar; FILE *fich; printf("Sauvegarde du niveau dans: %s...", nom); fich=fopen(nom, "wb"); if (fich==NULL) erreur("Impossible d'ouvrir le fichier en écriture", nom); fprintf(fich, "sol: %s\n", sol->nom); fprintf(fich, "bloc: %s\n", bloc->nom); fprintf(fich, "mur: %s\n", mur->nom); fprintf(fich, "fleche: %s\n", fleche->nom); fprintf(fich, "teleport: %s\n", teleport->nom); fprintf(fich, "tunnel: %s\n", tunnel->nom); fprintf(fich, "bouton: %s\n", bouton->nom); fprintf(fich, "fontaine: %s\n", fontaine->nom); fputc('\n', fich); fprintf(fich, "REGEN=%i\n", REGEN); fprintf(fich, "BONUSFREQ=%i\n", BONUSFREQ); fprintf(fich, "NBOMBES=%i\n", NBOMBES); fprintf(fich, "REBOURS=%i\n", REBOURS); fputc('\n', fich); for (i=0; i<8; i++) { fprintf(fich, "perso[%i]:(%i,%i)\n", i, persopos[i].x, persopos[i].y); } fprintf(fich, "\n\n{\n\n"); for(y=0; y<15; y++) { for(x=0; x<16; x++) { ncar=6; switch (pl[x][y].type) { case LIBRE : { fputc('_', fich); ncar--; if (pl[x][y].fixe) ncar -= fprintf(fich, "[%i]", pl[x][y].frame); }break; case DESTRUCTIBLE : { fputc('#', fich); ncar--; if (pl[x][y].fixe) ncar -= fprintf(fich, "[%i]", pl[x][y].frame); }break; case INDESTRUCTIBLE : { fputc('+', fich); ncar--; if (pl[x][y].fixe) ncar -= fprintf(fich, "[%i]", pl[x][y].frame); }break; case TUNNEL : { fputc('=', fich); ncar--; ncar -= fprintf(fich, "[%i]", pl[x][y].frame); }break; case SENSUNIQUE : { fputc('>', fich); ncar--; ncar -= fprintf(fich, "[%i]", pl[x][y].anim); }break; case EVENEMENT : { if (pl[x][y].elem==teleport) { fputc('T', fich); ncar--; i=0; do ncar -= fprintf(fich, "[%i]", pl[x][y].params[i]); while(++i0) { fputc(' ', fich); ncar--; } } fprintf(fich, "\n\n"); } fprintf(fich, "}\n\n"); fprintf(fich, legende); printf("OK\n"); fclose(fich); return; } void configurevt(int x, int y) { int i=0, j; int *params=pl[x][y].params; int nparams=pl[x][y].nparams; int xs[260], ys[260]; SDL_Event evt; if (x>15) return; for (i=0; ianims[1]->nframes, xs[j]*32, ys[j]*32); } SDL_Flip(ecran); SDL_PumpEvents(); if (SDL_PollEvent(&evt)) { if (evt.type==SDL_MOUSEBUTTONDOWN) { if (evt.button.button==1 && evt.button.x<16*32) { int n=0; int clx=evt.button.x/32; int cly=evt.button.y/32; do (SDL_WaitEvent(&evt)); while (evt.type!=SDL_MOUSEBUTTONUP); while (nnanims) { pl[x][y].anim=0; } } else if (pl[x][y].type!=EVENEMENT && pl[x][y].type!=LIBRE) { pl[x][y].frame++; if (pl[x][y].frame== pl[x][y].elem->anims[pl[x][y].anim]->nframes) { if (pl[x][y].fixe==1) pl[x][y].fixe=0; pl[x][y].frame=0; } } else if (pl[x][y].elem==teleport||pl[x][y].elem==bouton) { SDL_Event evt; do (SDL_WaitEvent(&evt)); while (evt.type!=SDL_MOUSEBUTTONUP); configurevt(x, y); } return; } void persodepart(void) { int i; SDL_Event evt; int nactif=0; int encore=1; int x, y; do { for (i=0; i<8; i++) { blitsprit(nb[i], 0, 1, persopos[i].x*32, persopos[i].y*32); blitsprit(sol, 0, 0, 17*32, i*32); blitsprit(nb[i], 0, 1, 17*32, i*32); } blitsprit(nived, 0, 1, 17*32, nactif*32); SDL_Flip(ecran); SDL_WaitEvent(&evt); if (evt.type==SDL_MOUSEBUTTONDOWN) { x=evt.button.x/32; y=evt.button.y/32; if (evt.button.button==3) encore=0; else if (x==17 && y<8) nactif=y; else if (x<16 && pl[x][y].type==LIBRE) { dessinecase(persopos[nactif].x, persopos[nactif].y); persopos[nactif].x=x; persopos[nactif].y=y; } } } while (encore); rdplateau(); return; } void changegraphs(void) { int i, x, y; char nom[256]; FILE *chgraphs, *svg; videcran(); sprintf(nom, "nived~"); sauveniv(nom); detruit_sprites(); nived=charge_sprite("nived.spr", 0); sprintf(nom, "%s/electr.g", prefixeniv); if (strcmp(graphtype, nom)) strcpy(graphtype, nom); else sprintf(graphtype, "%s/grotte.g", prefixeniv); chgraphs=fopen(graphtype, "rb"); if (chgraphs==NULL) erreur("Impossible d'ouvrir le fichier", graphtype); charge_graphs(chgraphs); fclose(chgraphs); sprintf(nom, "nived~"); svg=fopen(nom, "rb"); chargeniv(svg, 0); fclose(svg); initliste(); for (i=0; i<8; i++) { sprintf(nom, "%i.spr", i+1); nb[i]=charge_sprite(nom, decl); } elemactif.elem=sol; elemactif.type=LIBRE; elemactif.anim=0; elemactif.frame=0; elemactif.sol=0; elemactif.fixe=0; for (y=0; y<15; y++) for (x=0; x<16; x++) { pl[x][y].anim %= pl[x][y].elem->nanims; pl[x][y].frame %= pl[x][y].elem->anims[pl[x][y].anim]->nframes; } rdplateau(); return; } void cliccase(int x, int y, int b) { if (b==1 && pl[x][y].type==LIBRE) { pl[x][y].elem=elemactif.elem; pl[x][y].type=elemactif.type; pl[x][y].anim=elemactif.anim; pl[x][y].frame=elemactif.frame; pl[x][y].sol=elemactif.sol; pl[x][y].fixe=elemactif.fixe; pl[x][y].params[0]=elemactif.params[0]; pl[x][y].nparams=elemactif.nparams; } else if (b==3) { pl[x][y].elem=sol; pl[x][y].type=LIBRE; pl[x][y].anim=0; if (rand()>0.9*RAND_MAX) pl[x][y].anim = 1; pl[x][y].frame = aleat(sol->anims[pl[x][y].anim]->nframes); pl[x][y].sol=0; pl[x][y].fixe=0; } else tournelem(x, y); dessinecase(x, y); return; } void clicchoix(int x, int y, int b) { if (pl[x][y].elem==NULL) return; if (elemactif.elem==pl[x][y].elem) tournelem(x, y); elemactif.elem=pl[x][y].elem; elemactif.type=pl[x][y].type; elemactif.anim=pl[x][y].anim; elemactif.frame=pl[x][y].frame; elemactif.sol=pl[x][y].sol; elemactif.nparams=pl[x][y].nparams; elemactif.fixe=pl[x][y].fixe; actif.x=x; actif.y=y; return; } int clic(int x, int y, int b) { if (x<512) cliccase(x/32, y/32, b); else if (512+32<=x && x<512+64 && y<448) clicchoix(x/32-1, y/32, b); else if (17*32<=x && x<18*32 && y>=14*32) persodepart(); else if (18*32<=x && x<19*32 && y>=14*32) changegraphs(); return 0; } void initliste(void) { int i; elemliste[0]=sol; elemliste[1]=bloc; elemliste[2]=mur; elemliste[3]=fleche; elemliste[4]=teleport; elemliste[5]=tunnel; elemliste[6]=bouton; elemliste[7]=fontaine; for (i=0; i<8; i++) { pl[16][i].elem=elemliste[i]; pl[16][i].anim=0; pl[16][i].frame=0; pl[16][i].fixe=-1; pl[16][i].type=LIBRE; pl[16][i].sol=0; pl[16][i].nparams=0; pl[16][i].params[0]=0; } pl[16][0].fixe=0; pl[16][1].type=DESTRUCTIBLE; pl[16][1].sol=1; pl[16][1].fixe=0; pl[16][2].type=INDESTRUCTIBLE; pl[16][2].fixe=0; pl[16][3].type=SENSUNIQUE; pl[16][3].sol=1; pl[16][4].type=EVENEMENT; pl[16][4].sol=1; // pl[16][4].nparams=1; pl[16][5].type=TUNNEL; pl[16][6].type=EVENEMENT; pl[16][6].sol=1; // pl[16][6].nparams=1; pl[16][7].type=EVENEMENT; pl[16][7].sol=1; return; } void creeniveau(void) { int i, x, y; FILE *fich; sprintf(graphtype, "%s/electr.g", prefixeniv); fich = fopen(graphtype, "rb"); charge_graphs(fich); fclose(fich); for (y=0; y<15; y++) for (x=0; x<16; x++) { pl[x][y].elem=sol; pl[x][y].type=LIBRE; pl[x][y].anim=0; if (rand()>0.9*RAND_MAX) pl[x][y].anim = 1; pl[x][y].frame = aleat(sol->anims[pl[x][y].anim]->nframes); pl[x][y].sol=0; pl[x][y].fixe=0; } for (i=0; i<8; i++) { persopos[i].x=0; persopos[i].y=0; } REGEN=5; BONUSFREQ=2; NBOMBES=20; REBOURS=90; return; } void initedite(void) { FILE *niveau; int i; char nomniveau[256]; char nom[256]; compteur=0; encore=1; strcpy(nomniveau, niv); videcran(); printf("Ouverture du niveau: %s\n", nomniveau); niveau = fopen(nomniveau, "rb"); if (niveau==NULL) { creeniveau(); sauveniv(niv); } else { charge_graphs(niveau); chargeniv(niveau, 1); fclose(niveau); if (!strcmp(sol->nom, "circuit.spr")) sprintf(graphtype, "%s/electr.g", prefixeniv); else sprintf(graphtype, "%s/grotte.g", prefixeniv); } initliste(); for (i=0; i<8; i++) { sprintf(nom, "%i.spr", i+1); nb[i]=charge_sprite(nom, decl); } rdplateau(); SDL_Flip(ecran); elemactif.elem=sol; elemactif.type=LIBRE; elemactif.anim=0; elemactif.frame=0; elemactif.sol=0; elemactif.fixe=0; actif.x=16; actif.y=0; return; } int edite(void) { int x, y, bouton; SDL_Event evt; initedite(); do { if (compteur<65536) compteur++; else compteur=0; SDL_WaitEvent(&evt); if (evt.type==SDL_MOUSEBUTTONDOWN) { bouton=evt.button.button; x=evt.button.x; y=evt.button.y; clic(x,y,bouton); } else if (evt.type==SDL_KEYDOWN) { if (evt.key.keysym.sym==SDLK_s) sauveniv(niv); } rdicones(); blitsprit(nived, 0, 1, actif.x*32+32, actif.y*32); SDL_Flip(ecran); } while(encore); return 0; } /*--Recherche du répertoire d'installation--*/ char * rep_install(char * home) { char dir[256]; sprintf (dir, "%s/data/Sprites/citrouille.spr", "."); if (fopen(dir, "r")) return "./data"; sprintf (dir, "%s/data/Sprites/citrouille.spr", ".."); if (fopen(dir, "r")) return "../data"; sprintf (dir, "%s/Sprites/citrouille.spr", DIR); if (fopen(dir, "r")) return DIR; sprintf (dir, "%s/BomberInstinct/data/Sprites/citrouille.spr", home); if (fopen(dir, "r")) return strcat(home,"/BomberInstinct/data"); erreur("Le programme ne peut déterminer son répertoire d'installation.\nVérifiez qu'il est correctement installé",NULL); return NULL; } int main(int argc, char **argv) { int i; char home[256]; /*#ifndef win32 strcpy(home,getenv("HOME")); #else*/ sprintf(home, ""); /*#endif*/ strcpy(repertoire, rep_install(home)); printf("Données trouvées dans : %s.\n", repertoire); sprintf(prefixeniv, "%s/Niveaux", repertoire); sprintf(prefixespr, "%s/Sprites", repertoire); pleinecran=0; tout.x=tout.y=plateau.x=plateau.y=0; tout.h=plateau.h=480; tout.w=640; plateau.w=512; recdroite.x=512; recdroite.y=0; recdroite.w=128; recdroite.h=480; for (i=1; i