/* BOMBER INSTINCT */ /* Copyright © 2000 by Louis Gesbert and TeraSoft */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * Contact me at : metagribouille@netcourrier.com. * * +----------------------+ * Web site : |www.bomberinstinct.org| * +----------------------+ */ #include #include #include #include #include #include #include #include /* P.K. */ #include "macros.h" #include "types.h" #include "common.h" //x #include "main.h" // teporary for "Plateau" type #include "sprites.h" #include "pouvoirs.h" #include "niveaux.h" // P.K. //xx #include "niveaux2.h" #include "evenements.h" #include "options.h" #include "son.h" #include "gamelogic.h" #include "intro.h" /* P.K. Various languages localization */ #include #include /***********************************/ /*-----D é c l a r a t i o n s-----*/ /***********************************/ /*--Variables globales de configuration--*/ /* des options */ Uint32 flags = SDL_HWSURFACE|SDL_HWPALETTE; /* des fichiers */ //x char repertoire[256]; // path to bi char repertoire[MAX_STRING_LENGTH]; // path to bi //x char prefixeniv[256], prefixeimg[256]; // prefix paths char prefixeniv[MAX_STRING_LENGTH], prefixeimg[MAX_STRING_LENGTH]; // prefix paths //xchar prefixespr[256], prefixeson[256]; char prefixespr[MAX_STRING_LENGTH], prefixeson[MAX_STRING_LENGTH]; /*--Structures qui servent en continu dans le jeu--*/ //x P.K. Plateau pl[16][15]; /* Toutes les cases qui constituent le niveau */ Plan plan; // dynamic allocated gameplan //x P.K. Personnage perso[8]; /* Description de l'état des personnages */ Personnage perso[MAX_NPERSO]; /* Description de l'état des personnages */ int nperso = 2; /* réglage du nb de joueurs ds le menu */ //x Coord rscase[2][260]; int nrscase[2]={0,0}; /* Les cases à redessiner */ Coord rscase[2][MAX_NIVEWIDTH*MAX_NIVEHEIGHT+4]; int nrscase[2] = {0,0}; /* Les cases à redessiner */ //x Coord rstunnel[2][260]; int ntunnel[2]={0,0}; /* pareil, mais par-dessus le reste */ Coord rstunnel[2][MAX_NIVEWIDTH*MAX_NIVEHEIGHT+4]; int ntunnel[2] = {0,0}; /* pareil, mais par-dessus le reste */ //x SDL_Rect rsrect[512]; int nrsrect=0; /* Parties de l'écran à mettre à jour */ SDL_Rect rsrect[2*MAX_NIVEWIDTH*MAX_NIVEHEIGHT]; int nrsrect = 0; /* Parties de l'écran à mettre à jour */ int nrs = 0; /* sur quel buffer est le double-buffering */ Anims * anims = NULL; /* Animations à l'écran */ //x Anims * animsfin = NULL; /* On garde un pointeur sur le dernier élément Anims * animsfin; /* On garde un pointeur sur le dernier élément pour que les animations plus récentes passent par-dessus */ /*--Trucs dont le programme a besoin de se souvenir--*/ char **spritliste; SDL_Surface * bande; SDL_Surface * fondecran; SDL_Surface * txtmodesjeu[NMODES]; //x P.K.int score[8]; int score[MAX_NPERSO]; int enpause = 0; /*--Entrées/Sorties--*/ SDL_Surface *ecran; Uint8 *clavier; SDL_Joystick **joystick; int numjoys; /*--Variables qui servent en cours de jeu--*/ int compteur; int encore; /*--Variables des autres trucs dont on doit se souvenir quelque temps--*/ int danslemenu; int options; int choisi = 0; //x Coord fauxperso[8]; Coord fauxperso[MAX_NPERSO]; /* Resolution variables */ Resolution resolution; //x const int dx[4]={ 0, 0,-1, 1}; // moved to common.c P.K. /* Donne le déplacement en x à partir de la direction */ //x const int dy[4]={-1, 1, 0, 0}; /* Donne le déplacement en y à partir de la direction */ /********************************/ /*-------F o n c t i o n s------*/ /********************************/ /*--Initialiser SDL--*/ int init_sdl(void) { Uint32 params; SDL_Surface *icone; //x char chemin[256], titre[256]; // P.K. char chemin[MAX_STRING_LENGTH], titre[MAX_STRING_LENGTH]; char resolutionstring[MAX_STRING_LENGTH]; int ok; params = avecson ? SDL_INIT_VIDEO|SDL_INIT_AUDIO : SDL_INIT_VIDEO; if (avecjoy) params |= SDL_INIT_JOYSTICK; if ( SDL_Init(params) < 0 ) { printf(gettext("Impossible d'initialiser SDL: %s\n"), SDL_GetError()); exit(1); } if (avecjoy) { numjoys=SDL_NumJoysticks(); printf(gettext("%i joysticks détectés: support %s.\n"), numjoys, numjoys>0 ? "activé" : "désactivé"); } else { numjoys=0; printf(gettext("Support du joystick désactivé.\n")); } sprintf(titre, "Bomber Instinct - v%s", VERSION); SDL_WM_SetCaption(titre, "BomberInstinct"); sprintf(chemin, "%s/icone.bmp", prefixeimg); icone = SDL_LoadBMP(chemin); SDL_SetColorKey(icone, SDL_SRCCOLORKEY, 0); SDL_WM_SetIcon(icone, NULL); SDL_FreeSurface(icone); if (dblebuf) { flags |= SDL_DOUBLEBUF; } params = pleinecran ? flags|SDL_FULLSCREEN : flags; //x ok=SDL_VideoModeOK(640, 480, 8, params); ok = SDL_VideoModeOK(resolution.window_width, resolution.window_height, 8, params); if (!ok) { errormessage("Le mode vidéo requis n'est pas disponible", resolutionstring); } #ifdef DEBUG else if (ok!=8) { printf("Impossible de passer en mode couleurs 8 bits.\n"); printf("Le jeu tournera, mais en émulation donc plus lentement.\n"); } #endif //x ecran = SDL_SetVideoMode(640, 480, 8, params); ecran = SDL_SetVideoMode(resolution.window_width, resolution.window_height, 8, params); if ( ecran == NULL ) { printf("Impossible de choisir le mode 640*480 8 bits!\n%s\n", SDL_GetError()); return 1; } if ((ecran->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) { dblebuf = 1; printf("Double buffering: activé.\n"); } else if (dblebuf<2) { dblebuf = 0; printf("Double buffering: désactivé.\n"); } else { dblebuf = 1; } atexit(SDL_Quit); atexit(SDL_CloseAudio); SDL_EventState(SDL_APPMOUSEFOCUS | SDL_MOUSEBUTTONDOWN | SDL_MOUSEBUTTONUP | SDL_MOUSEMOTION | SDL_SYSWMEVENT, SDL_IGNORE); SDL_EnableKeyRepeat(0,0); SDL_ShowCursor(0); return 0; } /*--Initialisation des joysticks--*/ void initjoy(void) { int i; joystick=(SDL_Joystick **)calloc(sizeof(SDL_Joystick *), numjoys); for (i=0; iflags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) dblebuf=1; else dblebuf=0; return; } /*--Attend que le délai de boucle principale soit au moins VITESSE pour repartir--*/ int ajustevitesse(void) { static int repart=0; int t; #ifdef DEBUG int ecoule=repart ? SDL_GetTicks()-repart+VITESSE : VITESSE-1; #endif do { t = SDL_GetTicks(); } while (tformat->palette->ncolors, 10); SDL_PauseAudio(1); do SDL_WaitEvent(&evt); while (evt.type != SDL_KEYDOWN || !(SDL_GetAppState()&SDL_APPACTIVE)); restorepalette(pal, 50); SDL_PauseAudio(0); enpause=0; return; } /*--Affiche des informations, pose une question--*/ void dialogue(char * texte, int estunequestion) { // int nlignes=0; //x const char delim[]="#"; SDL_Event evt; paletsg pal; // char * lignes[256]; SDL_Surface *surf; //x surf=SDL_CreateRGBSurface (0, 640, 480, 16, 0,0,0,0); surf = SDL_CreateRGBSurface (0, resolution.window_width, resolution.window_height, 16, 0,0,0,0); while (SDL_PollEvent(&evt)); /* Vider la file d'évènements */ pal=changepalette(0.8, 0.8, 0.8, 0, 0, 1, ecran->format->palette->ncolors, 10); // while (lignes[nlignes]=strtok(texte, &delim)) nlignes++; XCenteredString(surf, 100,"Bonjour\nComment ça va ?"); SDL_BlitSurface(surf, NULL, ecran, NULL); rafraichit(); do SDL_WaitEvent(&evt); while (evt.type!=SDL_KEYDOWN || !(SDL_GetAppState()&SDL_APPACTIVE)); restorepalette(pal, 50); SDL_PauseAudio(0); enpause=0; return; } /*--Met en place des raccourcis-clavier--*/ 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_F10) exit(0); if (evt->key.keysym.sym == SDLK_F1) passenpleinecran(); if (evt->key.keysym.sym == SDLK_PAUSE) enpause=1; } if (evt->type == SDL_ACTIVEEVENT) { if (evt->active.type == SDL_APPACTIVE && !evt->active.gain) { enpause = 1; } } return 1; } /*--Affiche un écran noir--*/ void videcran(void) { //x SDL_Rect tout={0, 0, 640, 480}; SDL_Rect tout={0, 0, resolution.window_width, resolution.window_height}; // !! only plan + bande? !! SDL_FillRect(ecran, &tout, 0); SDL_Flip(ecran); if (dblebuf) { SDL_FillRect(ecran, &tout, 0); SDL_Flip(ecran); } return; } /*--Remet les structures utilisées pendant le jeu à zéro--*/ void reinit(void) { int i; Anims * a; Evenement * e; while (anims) { a=anims->suiv; free(anims); anims=a; } while (evts[AVANT]) { e=evts[AVANT]->suiv; free(evts[AVANT]); evts[AVANT]=e; } while (evts[APRES]) { e=evts[APRES]->suiv; free(evts[APRES]); evts[APRES]=e; } for (i=0; isuiv; free(perso[i].bombes); perso[i].bombes=pt; } } danslemenu=0; compteur=0; encore=1; nrsrect=0; nrscase[0]=0; nrscase[1]=0; nrs=0; ntunnel[0]=0; ntunnel[1]=0; decl=0; return; } /*--Règle les joysticks pour les joueurs--*/ void initjoy_persos() { int i; //x P.K. for (i=0; i<8; i++) { for (i=0; i < MAX_NPERSO; i++) { perso[i].cmd.joy=NULL; if (perso[i].cmd.bas==0 || perso[i].cmd.gauche==0 || perso[i].cmd.droite==0 || perso[i].cmd.b1==0 || perso[i].cmd.b2==0) { int njoy=perso[i].cmd.haut; if (njoy>=numjoys || joystick[njoy]==NULL) printf("Attention : Impossible d'initialiser le joystick %i demandé.\n", njoy); else perso[i].cmd.joy=joystick[njoy]; } } return; } /*--Initialise la structure perso avant chaque partie--*/ void initperso(int n) { perso[n].dir=BAS; perso[n].anim=BAS; perso[n].mv=0; perso[n].statut=VIVANT; perso[n].animdroite=REPOS; perso[n].energie=100; perso[n].lflammes=2; perso[n].bombes=NULL; perso[n].pos.x=perso[n].pos.y=0; if (spritliste[n]) initpouv(n); return; } /*--Ajoute un rectangle à rafraichir--*/ void rsrectplus(int x, int y, int w, int h) { rsrect[nrsrect].x = x; rsrect[nrsrect].y = y; rsrect[nrsrect].w = w; rsrect[nrsrect].h = h; nrsrect++; return; } /*--Ajoute une case du plateau à redessiner--*/ void rscaseplus(int x, int y) { int i; if (plan.element[x][y].type == TUNNEL) { /* On vérifie que la case n'est pas déjà présente car * le blit est le truc le plus lent. */ for (i = 0; i < ntunnel[nrs]; i++) { if (rstunnel[nrs][i].x == x && rstunnel[nrs][i].y == y) { return; } } //x if (ntunnel[nrs]<260) { if (ntunnel[nrs] < MAX_NIVEWIDTH*MAX_NIVEHEIGHT+4) { rstunnel[nrs][ntunnel[nrs]].x = x; rstunnel[nrs][ntunnel[nrs]].y = y; ntunnel[nrs]++; } } else { /* Idem */ for (i = 0; i < nrscase[nrs]; i++) { if (rscase[nrs][i].x == x && rscase[nrs][i].y == y) { return; } } //x if (nrscase[nrs] < 260) { if (nrscase[nrs] < MAX_NIVEWIDTH*MAX_NIVEHEIGHT+4) { rscase[nrs][nrscase[nrs]].x = x; rscase[nrs][nrscase[nrs]].y = y; nrscase[nrs]++; } } x *= 32; y *= 32; //x if ((!dblebuf) && nrsrect < 512) if ((!dblebuf) && nrsrect < 2*MAX_NIVEWIDTH*MAX_NIVEHEIGHT) { for (i = 0; i < nrsrect; i++) { if (rsrect[i].x == x && rsrect[i].y == y) { return; } } /* Ça marche parce que tous les rsrect * du plateau font au moins 32*32. */ rsrect[nrsrect].x = x; rsrect[nrsrect].y = y; rsrect[nrsrect].w = rsrect[nrsrect].h = 32; nrsrect++; } return; } /*--Ajoute une animation à la liste--*/ Anims * animsplus(Sprite *sprite, int anim, int vitesse, int duree, int x, int y) { Anims * nouv; nouv = (Anims *)malloc(sizeof(Anims)); if (anims) { anims->prec=nouv; } else { animsfin = nouv; } nouv->suiv=anims; nouv->prec=NULL; nouv->pos.x=x; nouv->pos.y=y; nouv->anim=anim; nouv->frame=0; nouv->vitesse=vitesse; nouv->duree=duree; nouv->sprite=sprite; if (vitesse) { nouv->compteur=0; } else { nouv->compteur=1; } anims = nouv; return nouv; } /*--Supprime l'animation a (a!=NULL)--*/ void animsmoins(Anims * a) { if (a == NULL) errormessage("Erreur interne 4654132 : veuillez contacter le programmeur", NULL); rscaseplus(a->pos.x, a->pos.y); if (a->suiv) { a->suiv->prec = a->prec; } if (a->prec) { a->prec->suiv = a->suiv; } else { if (a->suiv == NULL) { animsfin = NULL; } anims = a->suiv; } /* a est le premier élément de anims. anims doit maintenant pointer sur le suivant */ free(a); return; } /*--Redessine une case (x, y) du plateau--*/ void dessinecase(int ncases, Coord *co) { int i; for (i = 0; i < ncases; i++) { //x if ((danslemenu || !dblebuf) && nrsrect < 512) { if ((danslemenu || !dblebuf) && nrsrect < 2*MAX_NIVEWIDTH*MAX_NIVEHEIGHT) { //? rsrect[nrsrect].x = danslemenu ? 32*(co[i].x+2) : 32*co[i].x; rsrect[nrsrect].x = resolution.x_offset + (danslemenu ? 32*(co[i].x+2) : 32*co[i].x); //? rsrect[nrsrect].y = 32*co[i].y; rsrect[nrsrect].y = resolution.y_offset + 32*co[i].y; rsrect[nrsrect].w = rsrect[nrsrect].h = 32; nrsrect++; } if (danslemenu) { //? SDL_Rect rectorig = {rsrect[nrsrect-1].x-64, rsrect[nrsrect-1].y, //? rsrect[nrsrect-1].w , rsrect[nrsrect-1].h}; SDL_Rect rectorig = {rsrect[nrsrect-1].x-resolution.x_offset-64, rsrect[nrsrect-1].y-resolution.y_offset, rsrect[nrsrect-1].w, rsrect[nrsrect-1].h}; SDL_Rect rectdest=rsrect[nrsrect-1]; //? SDL_Rect rectdest = {rsrect[nrsrect-1].x+resolution.x_offset, rsrect[nrsrect-1].y+resolution.y_offset, //? rsrect[nrsrect-1].w , rsrect[nrsrect-1].h}; SDL_BlitSurface(fondecran, &rectorig, ecran, &rectdest); } else { if (plan.element[co[i].x][co[i].y].sol) { blitsprit(sol, 0, 0, co[i].x*32, co[i].y*32); } blitsprit(plan.element[co[i].x][co[i].y].elem, plan.element[co[i].x][co[i].y].anim, plan.element[co[i].x][co[i].y].frame, co[i].x*32, co[i].y*32); } } return; } /* A-t-on le droit de se rendre dans la case (x, y) * en allant dans la direction dir ? */ int partir(int x, int y, int dir) { int px, py; if (dir < 4) { px = x - dx[dir]; py = y - dy[dir]; //x P.K. if (px<0 || 15 non libre */ /* 1 -> libre */ /* -1 -> non libre mais destructible */ /* -2 -> non libre à cause d'une bombe */ int libre(int x, int y, int dir) { int ret=0; //x P.K. if (x<0 || 15= NBOMBES) || (plan.element[x][y].bombe)) { // && libre(x, y, 4)>0 return NULL; } perso[n].energie -= NBOMBES; nouv=(Bombe *)malloc(sizeof(Bombe)); if (perso[n].bombes) { perso[n].bombes->prec=nouv; } nouv->suiv=perso[n].bombes; nouv->prec=NULL; nouv->pos.x = x; nouv->pos.y = y; if (perso[n].statut & ETEINT) { nouv->rebours = -1; } else { nouv->rebours = REBOURS; } nouv->lflammes = perso[n].lflammes; nouv->car=0; if (perso[n].statut & DETONATEUR) { nouv->rebours = -1; } if (perso[n].statut & SUPERBOMBE) { nouv->car=SUPERBOMBE; perso[n].pouvactif[0]+=ACTIVATION; } perso[n].bombes=nouv; plan.element[x][y].bombe = BOMBE; return nouv; } /*--Supprime l'animation d'un bonus--*/ void bonusmoins(int x, int y) { Anims * pt=anims; while (pt) { if (pt->sprite==bonus && pt->pos.x==x && pt->pos.y==y) { animsmoins(pt); break; } pt=pt->suiv; } //animsplus destruction du bonus... return; } /*--Ramassage d'un bonus par un joueur--*/ void prendbonus(int n) { int x, y; x=perso[n].pos.x; y=perso[n].pos.y; bruitsplus(s_bonus, 1); switch(plan.element[x][y].params[0]) { case FLAMMESB: { perso[n].lflammes++; }break; case ENERGIEB: { perso[n].energie += (50+aleat(40)); if (perso[n].energie > 255) perso[n].energie = 255; }break; case POUVOIRB: { pouvoirplus(n, 0, 0); }break; } plan.element[x][y].type = LIBRE; bonusmoins(x,y); return; } /*--Affichage d'un joueur à l'écran--*/ void afficheperso(int n, int frame) { if (perso[n].statut&INVISIBLE) return; else if (perso[n].statut&DEGUISE) blitsprit(mur,2,0,perso[n].pixpos.x, perso[n].pixpos.y); else if (sprit[n]->anims[0]->nframes<8) /* Autrement dit, le personnage est une citrouille */ blitsprit(sprit[n], 0, (compteur/2)%sprit[n]->anims[0]->nframes, perso[n].pixpos.x,perso[n].pixpos.y); else blitsprit(sprit[n],perso[n].anim,frame,perso[n].pixpos.x,perso[n].pixpos.y); return; } /*--Anime les mouvements des joueurs--*/ void animouv(int n) { int dirx, diry; int mv, frame=0; int x, y; x=perso[n].pos.x; y=perso[n].pos.y; perso[n].pixpos.x = x*32; perso[n].pixpos.y = y*32; dirx=dx[perso[n].dir]; diry=dy[perso[n].dir]; mv=perso[n].mv; //if (perso[n].action!=RIEN || perso[n].action==INVINCIBLE) perso[n].anim=perso[n].dir; /* Si le personnage est déguisé, pour lui les propriétés */ /* de sa case restent les mêmes même si elles changent pour */ /* les autres. */ if (perso[n].statut & DEGUISE) { plan.element[x][y].type = perso[n].pouvoirparam; } rscaseplus(x, y); if (mv > 0) { perso[n].pixpos.x+=4*mv*dirx; perso[n].pixpos.y+=4*mv*diry; rscaseplus(x+dirx, y+diry); frame=mv; } if (mv == -1 || (perso[n].statut&RAPIDE && mv == -2) ) { if (plan.element[x][y].type == EVENEMENT) { evtsplus(plan.element[x][y].evt, n, x, y, 0, 1, plan.element[x][y].nparams ? plan.element[x][y].params[0] : 0, APRES, NULL); } if (plan.element[x][y].type == BONUS) { prendbonus(n); } } if (mv<0) { mv++; /* mv est artificiellement minoré de 1 pour distinguer */ /* quand le personnage arrive sur une case ou s'il y est déjà */ perso[n].pixpos.x+=4*mv*dirx; perso[n].pixpos.y+=4*mv*diry; if (mv) { rscaseplus(x-dirx, y-diry); frame = 8+mv; } /* (mv<=0) */ else { frame = 0; } } afficheperso(n, frame); /* Le personnage est déguisé, les autres le prennent donc pour un mur */ if (perso[n].statut & DEGUISE) { perso[n].pouvoirparam=plan.element[x][y].type; plan.element[x][y].type=CAMOUFL; } if (perso[n].mv) { perso[n].mv++; } /* Les 4 premières frames de mouvement sont positives (1..4) */ /* et les 4 dernières négatives (-5..-1 -> -4..-0) */ /* Comme ça le personnage est considéré comme étant sur la case */ /* dont il est le plus proche. */ if (perso[n].mv==4) { if (perso[n].statut & DEGUISE) { plan.element[x][y].type=perso[n].pouvoirparam; perso[n].pouvoirparam=plan.element[x+dirx][y+diry].type; plan.element[x+dirx][y+diry].type=CAMOUFL; } perso[n].pos.y+=diry; perso[n].pos.x+=dirx; perso[n].mv=-5; } if (perso[n].mv && perso[n].statut&RAPIDE) perso[n].mv++; return; } /*--Tentative d'assassinat du personnage "tue" par une bombe de "tueur"--*/ void mort(int tueur, int tue) { int i, n_en_vie=0; if (perso[tue].statut&INVINCIBLE || !(perso[tue].statut&VIVANT)) { return; } if (perso[tue].statut&DEGUISE) { plan.element[perso[tue].pos.x][perso[tue].pos.y].type=perso[tue].pouvoirparam; } if (modejeu == MODE_DEATHMATCH_GORE || (modejeu == MODE_DEATHMATCH && tueur!=tue)) { score[tueur]++; } perso[tue].statut = MORT; perso[tue].animdroite = AGONIE; if (sprit[tue]->nanims > 7) { animsplus(sprit[tue], ANIM_MORT, 4, 1, perso[tue].pos.x, perso[tue].pos.y); } bruitsplus(s_mort, 1); for (i=0; i < NB_PERSO; i++) { if (perso[i].statut&VIVANT) { n_en_vie++; } } if (n_en_vie<2) { evtsplus(termine, 0, 0, 0, 100, 1, 0, APRES, NULL); } return; } /*--Effet mortel sur la case (x,y), à cause du joueur n--*/ void tue(int x, int y, int n) { int i; for (i=0; i < NB_PERSO; i++) { if (perso[i].pos.x == x && perso[i].pos.y == y) { mort(n, i); } } return; } /*--Explosion d'une bombe--*/ void explose(int n, Bombe * b) { void propagflam(int, int, int, int, int); plan.element[b->pos.x][b->pos.y].bombe = EXPL; evtsplus(destruction, n, b->pos.x, b->pos.y, 0, 1, 0, AVANT, NULL); bruitsplus(s_expl, 1); if (b->suiv) { b->suiv->prec=b->prec; } if (b->prec) { b->prec->suiv=b->suiv; } else { // b est la première bombe, "bombes" pointe maintenant sur b->suiv perso[n].bombes = b->suiv; } tue(b->pos.x, b->pos.y, n); propagflam(n, b->pos.x, b->pos.y, b->lflammes, b->car == SUPERBOMBE); free(b); return; } /*--Détecte la bombe de la case (x,y) pour la faire exploser--*/ void explosebombe(int x, int y) { int i; Bombe * pt; for (i=0; i < NB_PERSO; i++) { pt = perso[i].bombes; while (pt) { if (pt->pos.x == x && pt->pos.y == y) { pt->rebours = 1; return; } pt = pt->suiv; } } return; /* Ne devrait servir à rien */ } /*--Casse un mur destructible--*/ void detruitbloc(int x, int y) { int param; plan.element[x][y].elem = sol; plan.element[x][y].anim = 0; plan.element[x][y].frame = 0; plan.element[x][y].type = LIBRE; plan.element[x][y].bombe = EXPL; evtsplus(destruction, 0, x, y, 0, 1, 0, AVANT, NULL); animsplus(bloc, 1, 2, 1, x, y); //* if (aleat(BONUSFREQ)==0) if (aleatfloat(bonus_freq)==0) { param=aleat(10); plan.element[x][y].params=(int *)malloc(sizeof(int)); plan.element[x][y].nparams=1; if (0<=param && param<5) plan.element[x][y].params[0] = FLAMMESB; else if (5<=param && param<9) plan.element[x][y].params[0] = ENERGIEB; else if (9<=param && param<10) plan.element[x][y].params[0] = POUVOIRB; plan.element[x][y].type=BONUS; animsplus(bonus, plan.element[x][y].params[0], 2, 0, x, y); } return; } /*--Propagation des flammes des bombes--*/ void propagflam(int n, int ox, int oy, int lflammes, int sup) { int i, j; int x, y; int type; int anim; int caselibre; for (i=0; i < 4; i++) // four directions { for (j = 1; j <= lflammes; j++) // length of the flame { x = ox+dx[i]*j; y = oy+dy[i]*j; //x P.K. if (x<0 || x>15 || y<0 || y>14) if (x < 0 || x >= plan.nivewidth || y < 0 || y >= plan.niveheight) { break; } if (!partir(x, y, i)) { break; } caselibre = libre(x, y, i); type = plan.element[x][y].type; /* Contrairement aux personnages, * les flammes font peu de cas du déguisement */ if (plan.element[x][y].type == CAMOUFL) { caselibre = 1; } if (caselibre == -2) { /* S'il y a une bombe mais que ç'aurait été libre sinon */ tue(x, y, n); explosebombe(x,y); if (!sup) { break; } } else if (!caselibre && plan.element[x][y].type == TUNNEL) { /* Il y a un tunnel qui empêche le passage de la flamme */ break; } else if (plan.element[x][y].bombe == EXPL) { /* L'élément a été détruit à ce round */ tue(x, y, n); if (!sup) { break; } } else if (type == BONUS) { tue(x, y, n); plan.element[x][y].type = LIBRE; plan.element[x][y].bombe = EXPL; evtsplus(destruction, n, x, y, 0, 1, 0, AVANT, NULL); bonusmoins(x,y); if (!sup) { break; /* Les super-flammes continuent leur chemin */ } else { anim = (j == lflammes) ? (i+3) : (i/2+1); animsplus(flammes, anim, 2, 1, x, y); } } else if (caselibre>0 && plan.element[x][y].elem!=mur) { tue(x, y, n); anim = (j==lflammes) ? (i+3) : (i/2+1); animsplus(flammes, anim, 2, 1, x, y); } else if (plan.element[x][y].elem == mur) { int animbrule = plan.element[x][y].frame+1; tue(x, y, n); if (animbrule < mur->nanims && mur->anims[animbrule]->nframes> 1 && plan.element[x][y].anim == 0) { animsplus(mur, animbrule, 2, 1, x, y); plan.element[x][y].anim = animbrule; plan.element[x][y].frame = mur->anims[animbrule]->nframes-1; } break; } else if (type == DESTRUCTIBLE) { tue(x, y, n); detruitbloc(x, y); if (sup) { anim = (j == lflammes) ? (i+3) : (i/2+1); animsplus(flammes, anim, 2, 1, x, y); } else break; } else break; } } animsplus(bombe, 5, 2, 1, ox, oy); return; } /*--Rafraichir l'écran (à chaque frame), suivant le mode--*/ int rafraichit(void) { if (dblebuf) { SDL_Flip(ecran); nrsrect=0; nrs=!nrs; } else { SDL_UpdateRects(ecran, nrsrect, rsrect); nrsrect=0; nrs=0; } return; } /*--Dessine la jauge d'énergie du joueur n à droite de l'écran--*/ void jauge(int n) { SDL_Rect jauge; SDL_Rect energie; //x jauge.x = 523; jauge.x = resolution.x_offset+resolution.plan_width+11; //x jauge.y = n*48+114; jauge.y = resolution.y_offset+n*48+114; jauge.w = 106; jauge.h = 10; // energie.x = 525; energie.x = resolution.x_offset+resolution.plan_width+13; //x energie.y = n*48+116; energie.y = resolution.y_offset+n*48+116; energie.w = 102; energie.h = 6; if (!(perso[n].statut&VIVANT)) { SDL_FillRect(ecran, &jauge, 1); return; } if (perso[n].pouvactif[0]) { //x blitsprit(sprit[n], ICONES, 2*((compteur/3)%2), 567, 48*n+80); blitsprit(sprit[n], ICONES, 2*((compteur/3)%2), resolution.plan_width+55, 48*n+80); } else if (perso[n].energie>=perso[n].pouv[0].energie) { //x blitsprit(sprit[n], ICONES, 0, 567, 48*n+80); blitsprit(sprit[n], ICONES, 0, resolution.plan_width+55, 48*n+80); } else { //x blitsprit(sprit[n], ICONES, 2, 567, 48*n+80); blitsprit(sprit[n], ICONES, 2, resolution.plan_width+55, 48*n+80); } if (perso[n].pouvactif[1]) { //x blitsprit(sprit[n], ICONES, 1+2*((compteur/3)%2), 599, 48*n+80); blitsprit(sprit[n], ICONES, 1+2*((compteur/3)%2), resolution.plan_width+87, 48*n+80); } else if (perso[n].energie>=perso[n].pouv[1].energie) { //x blitsprit(sprit[n], ICONES, 1, 599, 48*n+80); blitsprit(sprit[n], ICONES, 1, resolution.plan_width+87, 48*n+80); } else { //x blitsprit(sprit[n], ICONES, 3, 599, 48*n+80); blitsprit(sprit[n], ICONES, 3, resolution.plan_width+87, 48*n+80); } energie.w = perso[n].energie/2.5; SDL_FillRect(ecran, &jauge, 1); SDL_FillRect(ecran, &energie, 2); return; } /*--Dessine la bande de droite (jauges, etc.)--*/ void dessinebande(void) { int i; //x SDL_Rect recdroite={512, 0, 128, 480}; //? SDL_Rect recdroite={resolution.plan_width+resolution.x_offset, resolution.y_offset, 128, 480}; SDL_Rect recdroite = {resolution.plan_width+resolution.x_offset, resolution.y_offset, 128, resolution.plan_height}; //x SDL_Rect recbande={512, 0, 128, 80}; SDL_Rect recbande = {resolution.plan_width+resolution.x_offset, resolution.y_offset, 128, 80}; SDL_FillRect(ecran, &recdroite, 0); SDL_BlitSurface(bande, NULL, ecran, &recbande); rsrectplus(recdroite.x, recdroite.y, recdroite.w, recdroite.h); for (i=0; i < NB_PERSO; i++) { int y = 48*i+80; jauge(i); if (!(perso[i].statut&VIVANT)) { if (sprit[i]->nanims <= ANIM_MORT) //x blitsprit(bombe, 7, (compteur/3)%4, 525, y); blitsprit(bombe, 7, (compteur/3)%4, resolution.plan_width+13, y); else if (AGONIE <= perso[i].animdroite) { //x blitsprit(sprit[i], ANIM_MORT, (perso[i].animdroite-AGONIE)/3, 525, y); blitsprit(sprit[i], ANIM_MORT, (perso[i].animdroite-AGONIE)/3, resolution.plan_width+13, y); if ( (++perso[i].animdroite - AGONIE)/3 >= sprit[i]->anims[ANIM_MORT]->nframes) { perso[i].animdroite = ANIM_MORT; } } else { //x blitsprit(sprit[i], ANIM_MORT, sprit[i]->anims[ANIM_MORT]->nframes-1, 525, y); blitsprit(sprit[i], ANIM_MORT, sprit[i]->anims[ANIM_MORT]->nframes-1, resolution.plan_width+13, y); } } else { if (perso[i].animdroite >= sprit[i]->nanims) { perso[i].animdroite = BAS; } //x blitsprit(sprit[i], perso[i].animdroite, (compteur/4) % sprit[i]->anims[perso[i].animdroite]->nframes, 525, y); blitsprit(sprit[i], perso[i].animdroite, (compteur/4) % sprit[i]->anims[perso[i].animdroite]->nframes, resolution.plan_width+13, y); } //x rsrect[nrsrect].x = 523; rsrect[nrsrect].x = resolution.plan_width+9; rsrect[nrsrect].y = y; rsrect[nrsrect].w = 106; rsrect[nrsrect].h = 32+12; nrsrect++; } } /*--Annonce que tout devra être redessiné à la prochaine frame--*/ void rdtout(void) { int x, y; //x P.K. for (y=0; y<15; y++) for (y=0; y < plan.niveheight; y++) //x P.K. for (x=0; x<16; x++) for (x=0; x < plan.nivewidth; x++) { if (plan.element[x][y].type == TUNNEL) { rstunnel[nrs][ntunnel[nrs]].x = x; rstunnel[nrs][ntunnel[nrs]].y = y; ntunnel[nrs]++; } else { rscase[nrs][nrscase[nrs]].x = x; rscase[nrs][nrscase[nrs]].y = y; nrscase[nrs]++; } } return; } /*--Redessiner les cases de décor--*/ void rdplateau(int rien) { nrscase[0]=0; nrscase[1]=0; ntunnel[0]=0; ntunnel[1]=0; nrsrect=0; rdtout(); if (dblebuf) { nrs = !nrs; rdtout(); } return; } /*--Gère les bombes--*/ void anibombes() { Bombelist * anibombes2(int n, Bombe * b); void anibombes3(int n, Bombelist * b); int i=0; Bombelist * imminent[NB_PERSO]; while (i < NB_PERSO) { imminent[i]=anibombes2(i, perso[i].bombes); i++; } /* On met à jour les états de toutes les bombes */ i=0; while (i < NB_PERSO) { anibombes3(i, imminent[i]); i++; } /* Puis on fait exploser celles qui en ont besoin */ return; } Bombelist * anibombes2(int n, Bombe * b) { int frame, anim; Bombe * suiv; if (b == NULL) { return NULL; } suiv=b->suiv; if (b->rebours) { if (b->rebours>0) { anim= (5 * (REBOURS - b->rebours)) / REBOURS; b->rebours--; frame=((REBOURS - b->rebours) /3) % bombe->anims[anim]->nframes; } else { anim=7; frame=(compteur/3)%bombe->anims[anim]->nframes; } rscaseplus(b->pos.x, b->pos.y); blitsprit(bombe, anim, frame, b->pos.x*32, b->pos.y*32); return anibombes2(n,suiv); } else { Bombelist * nouv=(Bombelist *)malloc(sizeof(Bombelist)); nouv->contenu=b; nouv->suiv=anibombes2(n,suiv); return nouv; } } void anibombes3(int n, Bombelist * bl) { Bombelist * suiv; if (bl == NULL) { return; } suiv = bl->suiv; explose (n,bl->contenu); free(bl); anibombes3(n,suiv); return; } /*--Gère la structures anims--*/ void anime(Anims * a) { Anims * prec; /* On parcourt la liste des animations en ordre inverse pour que les plus récentes soient affichées au-dessus des plus anciennes */ if (a == NULL) { return; } prec = a->prec; rscaseplus(a->pos.x, a->pos.y); blitsprit(a->sprite, a->anim, a->frame, a->pos.x*32, a->pos.y*32); if (a->vitesse) { a->compteur++; } if (a->compteur == a->vitesse) { a->compteur=0; if (a->frame < a->sprite->anims[a->anim]->nframes-1) { a->frame++; } else { a->frame=0; if (a->duree) { a->duree--; if (!a->duree) animsmoins(a); } } } anime(prec); return; } /*--trie les volontés de déplacement des joueurs--*/ void mouvement(int n, int dir) { int x, y, stat; x=perso[n].pos.x+dx[dir]; y=perso[n].pos.y+dy[dir]; if (perso[n].statut & DEGUISE) plan.element[perso[n].pos.x][perso[n].pos.y].type=perso[n].pouvoirparam; stat=libre(x, y, dir); if (stat>0) perso[n].mv=1; else if (perso[n].statut & FURIEDESTRUCTRICE && stat==-1) { detruitbloc(x, y); bruitsplus(s_expl, 1); perso[n].mv=1; } else if (perso[n].statut & PASSEMURAILLES //x P.K. && 0<=perso[n].pos.x+dx[dir] && perso[n].pos.x+dx[dir]<16 && 0 <= perso[n].pos.x+dx[dir] && perso[n].pos.x+dx[dir] < plan.nivewidth //x P.K. && 0<=perso[n].pos.y+dy[dir] && perso[n].pos.y+dy[dir]<15) && 0 <= perso[n].pos.y+dy[dir] && perso[n].pos.y+dy[dir] < plan.niveheight) perso[n].mv=1; if (perso[n].statut & DEGUISE) { perso[n].pouvoirparam=plan.element[perso[n].pos.x][perso[n].pos.y].type; plan.element[perso[n].pos.x][perso[n].pos.y].type=CAMOUFL; } return; } /*--trie les commandes des joueurs et renvoie un bitmask--*/ int commande(int n) { int cmd=0x0; perso[n].cmd.precedent=perso[n].cmd.actif; if (perso[n].joueurIA) return perso[n].cmd.actif=gamelogic_main(n); else if (perso[n].cmd.joy==NULL) { if (clavier[perso[n].cmd.haut]==SDL_PRESSED) cmd|=CMD_HAUT; if (clavier[perso[n].cmd.bas]==SDL_PRESSED) cmd|=CMD_BAS; if (clavier[perso[n].cmd.gauche]==SDL_PRESSED) cmd|=CMD_GAUCHE; if (clavier[perso[n].cmd.droite]==SDL_PRESSED) cmd|=CMD_DROITE; if (clavier[perso[n].cmd.b1]==SDL_PRESSED) cmd|=CMD_B1; if (clavier[perso[n].cmd.b2]==SDL_PRESSED) cmd|=CMD_B2; } else { int var=SDL_JoystickGetAxis(perso[n].cmd.joy, 1); if (var < -100) cmd|=CMD_HAUT; if (var > 100) cmd|=CMD_BAS; var=SDL_JoystickGetAxis(perso[n].cmd.joy, 0); if (var < -100) cmd|=CMD_GAUCHE; if (var > 100) cmd|=CMD_DROITE; if (SDL_JoystickGetButton(perso[n].cmd.joy, 0)) cmd|=CMD_B1; if (SDL_JoystickGetButton(perso[n].cmd.joy, 1)) cmd|=CMD_B2; } return perso[n].cmd.actif=cmd; } /*--Gère les commandes des joueurs--*/ void touches(int n) { int p=0; int cmd=commande(n); if (!danslemenu) { if (cmd&CMD_B2) { p=1; if (cmd&CMD_GAUCHE) pouvoirplus(n, 0, 1); if (cmd&CMD_DROITE) pouvoirplus(n, 1, 1); if (cmd&CMD_HAUT) pouvoirplus(n, 2, 1); if (cmd&CMD_BAS) pouvoirplus(n, 3, 1); } } if (p); else if (cmd&CMD_HAUT && !perso[n].mv) { perso[n].dir=HAUT; mouvement(n, HAUT); } else if (cmd&CMD_BAS && !perso[n].mv) { perso[n].dir=BAS; mouvement(n, BAS); } else if (cmd&CMD_GAUCHE && !perso[n].mv) { perso[n].dir=GAUCHE; mouvement(n, GAUCHE); } else if (cmd&CMD_DROITE && !perso[n].mv) { perso[n].dir=DROITE; mouvement(n, DROITE); } if (!danslemenu) if (cmd&CMD_B1) { if (perso[n].statut & DETONATEUR) { Bombe * pt = perso[n].bombes; evtsplus(restorestatut, n, 0, 0, 6, 1, DETONATEUR, APRES, NULL); while (pt) { if (pt->rebours==-1) pt->rebours=0; pt=pt->suiv; } } else if(!(perso[n].statut&PASBOMBES)) posebombe(perso[n].pos.x, perso[n].pos.y, n); } return; } /*--Écran de menu des choix de personnages--*/ int choix(char *nom, char *image) { int i; FILE *niveau; //x char chemin[256]; char chemin[MAX_STRING_LENGTH]; SDL_Rect recfond; SDL_Color pal[255]; danslemenu=2; compteur=0; nrsrect=0; nrscase[0]=0; nrscase[1]=0; nrs=0; ntunnel[0]=0; ntunnel[1]=0; options=0; encore=1; videcran(); if (Mix_PlayingMusic) Mix_HaltMusic(); //if (avecmusique) Mix_PlayMusic(muschoix, -1); for (i=0; iformat->palette->colors, decl, fondecran->format->palette->ncolors); decl += fondecran->format->palette->ncolors; charge_graphs(niveau); charge_sprites(sprit, spritliste, NB_PERSO); charge_sprites(fauxsprit, persoliste, nsprit); for (i=0; i < NB_PERSO; i++) { initperso(i); } //x chargeniv(niveau); // P.K. freeplan(&plan); chargeniv_dynamic(niveau, &plan, 1, danslemenu, 0); fclose(niveau); //? recfond.x=recfond.y=0; recfond.x = resolution.x_offset; recfond.y = resolution.y_offset; //? recfond.w=512; recfond.h=480; recfond.w = resolution.plan_width; recfond.h = resolution.plan_height; /* Mettre en noir et blanc */ for (i=1; i < 256 && iformat->palette->ncolors; i++) { SDL_Color *colors = ecran->format->palette->colors; float moy = (colors[i].r+colors[i].g+colors[i].b)/3.0; moy = ((moy-30-127)*0.68)+127; /* luminosité -20 contraste -40 */ pal[i-1].r = (moy >= 225) ? 255 : moy+30; pal[i-1].g = moy; pal[i-1].b = (moy <= 30) ? 0 : moy-30; } SDL_SetColors(ecran, pal, 1, 256); rdplateau(0); do { ajustevitesse(); if (compteur<65536) { compteur++; } else { compteur = 0; } dessinecase(nrscase[nrs], rscase[nrs]); if (dblebuf) { dessinecase(nrscase[!nrs], rscase[!nrs]); } nrscase[nrs] = 0; anime(animsfin); SDL_PumpEvents(); clavier = SDL_GetKeyState(NULL); for (i=0; i < nsprit; i++) { if (strcmp(persoliste[i], "citrouille.spr")) { blitsprit(fauxsprit[i], 1, 0, fauxperso[i].x*32, fauxperso[i].y*32); } } for (i=0; i < NB_PERSO; i++) { if (perso[i].statut&VIVANT) { touches(i); animouv(i); } } //dessinecase(ntunnel, rstunnel); //ntunnel=0; agit(evts[APRES], APRES); rafraichit(); } while(encore && clavier[SDLK_ESCAPE]!=SDL_PRESSED && clavier[SDLK_F8]!=SDL_PRESSED); reinit(); detruit_sprites(); SDL_FreeSurface(fondecran); if (clavier[SDLK_ESCAPE] == SDL_PRESSED) { while(clavier[SDLK_ESCAPE] == SDL_PRESSED) { SDL_PumpEvents(); clavier=SDL_GetKeyState(NULL); } return 1; } else if (clavier[SDLK_F8] == SDL_PRESSED) { while(clavier[SDLK_ESCAPE] == SDL_PRESSED || clavier[SDLK_F8] == SDL_PRESSED) { SDL_PumpEvents(); clavier=SDL_GetKeyState(NULL); } return 2; } choisi = 1; return 0; } /*--Écran de menu principal et options--*/ int menu(int principal, char *nom, char *image) { int i; int preums; FILE *niveau; //x char chemin[256]; char chemin[MAX_STRING_LENGTH]; //x SDL_Rect recmodejeu = {225+resolution.x_offset, 320+resolution.y_offset, 341, 31}; SDL_Rect recmodejeu = {225+resolution.x_offset, 320+resolution.y_offset, 341, 31}; danslemenu=1; compteur=0; nrsrect=0; nrscase[0]=0; nrscase[1]=0; nrs=0; ntunnel[0]=0; ntunnel[1]=0; options=0; encore=1; //x P.K. for (i=0; i<8; i++) for (i=0; i < MAX_NPERSO; i++) { score[i] = 0; } nperso = NB_PERSO; videcran(); decl = 0; couleurs = charge_sprite("infos.spr", decl); sprintf(chemin, "%s/%s", prefixeniv, nom); niveau = fopen(chemin, "r"); if (niveau == NULL) { errormessage("Impossible d'ouvrir le fichier menu", nom); } sprintf(chemin, "%s/%s", prefixeimg, image); fondecran = SDL_LoadBMP(chemin); if (fondecran == NULL) { errormessage("Impossible de charger l'image", image); } SDL_SetColors(ecran, fondecran->format->palette->colors, decl, fondecran->format->palette->ncolors); decl += fondecran->format->palette->ncolors; if (!principal) { for (i=0; i < NMODES; i++) { sprintf(chemin, "%s/mode_%i.bmp", prefixeimg, i); txtmodesjeu[i] = SDL_LoadBMP(chemin); if (txtmodesjeu[i] == NULL) { errormessage("Impossible de charger l'image", image); } } } charge_graphs(niveau); sprit[0] = charge_sprite("citrouille.spr", decl); for (i=0; i < NB_PERSO; i++) { initperso(i); } //x chargeniv(niveau); // P.K. freeplan(&plan); chargeniv_dynamic(niveau, &plan, 1, danslemenu, 0); fclose(niveau); rdplateau(0); preums = 1+dblebuf; do { ajustevitesse(); if (compteur < 65536) { compteur++; } else { compteur = 0; } dessinecase(nrscase[nrs], rscase[nrs]); if (dblebuf) { dessinecase(nrscase[!nrs], rscase[!nrs]); } nrscase[nrs] = 0; anime(animsfin); if (principal) { blitsprit(couleurs, 1, 0, (3+nperso)*32, 9*32); } agit(evts[AVANT], AVANT); SDL_PumpEvents(); clavier = SDL_GetKeyState(NULL); touches(0); animouv(0); agit(evts[APRES], APRES); //dessinecase(ntunnel, rstunnel); //ntunnel=0; if (preums && !principal) { /* c-à-d menu des options */ SDL_BlitSurface(txtmodesjeu[modejeu], NULL, ecran, &recmodejeu); rsrectplus(161, 320, 341, 31); //? rsrectplus(161+resolution.x_offset, 320+resolution.y_offset, 341, 31); } rafraichit(); if (clavier[SDLK_ESCAPE] == SDL_PRESSED) { exit(0); } if (preums) preums--; } while(encore); reinit(); detruit_sprites(); SDL_FreeSurface(fondecran); if (!principal) { for (i=0; i < NMODES; i++) { SDL_FreeSurface(txtmodesjeu[i]); } } if (principal) { NB_PERSO = nperso; } if (options) { menu(0, "options.niv", choixlangue(chemin, "Options", "bmp")); return 1; } return 0; } /*--Évenements déclenchés dans les menus--*/ void menuevt(Evenement * e) { int val, i, n_restant=0; int x = e->pos.x; int y = e->pos.y; int p = e->proprietaire; int param = plan.element[x][y].params[0]; if (param == SUIVANT) { encore=0; bruitsplus(s_teleport, 1); } else if (MINNB < param && param < MAXNB) { rdplateau(0); nperso = param-110; bruitsplus(s_bouton, 1); } else if (MINTOUCHES < param && param < MAXTOUCHES) { touchescfg(x, y, param-221); } else if (param == SAUVECONFIG) { sauvecfg(); } else if (param == OPTIONS) { options = 1; encore = 0; } else if (param == MODEDEJEU || param == MODEDEJEUPLUS) { //x SDL_Rect recmodejeu = {225, 320, 341, 31}; SDL_Rect recmodejeu = {225+resolution.x_offset, 320+resolution.y_offset, 341, 31}; if (param == MODEDEJEUPLUS) { modejeu = NMODES -1; } else { modejeu = (modejeu+1) % (NMODES-1); } SDL_BlitSurface(txtmodesjeu[modejeu], NULL, ecran, &recmodejeu); if (dblebuf) { SDL_Flip(ecran); SDL_BlitSurface(txtmodesjeu[modejeu], NULL, ecran, &recmodejeu); SDL_Flip(ecran); } else { //x rsrectplus(161, 320, 341, 31); rsrectplus(161+resolution.x_offset, 320+resolution.y_offset, 341, 31); } bruitsplus(s_bouton, 1); } else if (param == QUITTER) { exit(0); } else if (MINPERSO < param && param < MAXPERSO) { val = param-121; if (valproprietaire = i; /* ??? */ } } if (!n_restant) { encore = 0; if (Mix_PlayingMusic) { Mix_HaltMusic(); } } else { bruitsplus(s_teleport, 1); } } return; } /*--Boucle principale du jeu--*/ int jeu(void) { paletsg pal; int preums=1; int i; #ifdef DEBUG int i; Uint32 stat[10000]; int nstat=0; int nral=0; float moy=0; #endif if (!dblebuf) { pal = changepalette(0.0, 0.0, 0.0, 1, 256, 256, 256, 0); /* tout noir */ } rdplateau(0); bruitsplus(s_debut, 1); do { #ifdef DEBUG if (nstat<10000) { stat[nstat++] = ajustevitesse(); } else { ajustevitesse(); } #else ajustevitesse(); #endif if (compteur<65536) { compteur++; } else { compteur=0; } dessinecase(nrscase[nrs], rscase[nrs]); if (dblebuf) { dessinecase(nrscase[!nrs], rscase[!nrs]); } nrscase[nrs] = 0; SDL_PumpEvents(); clavier = SDL_GetKeyState(NULL); agit(evts[AVANT], AVANT); anime(animsfin); anibombes(); //x while (i < NB_PERSO) // for is better P.K. for (i=0; i < NB_PERSO; i++) { if (perso[i].statut&VIVANT) { if (compteur%REGEN == 0) { if (perso[i].energie < 255) { perso[i].energie++; } } touches(i); animouv(i); } //x i++; } agit(evts[APRES], APRES); dessinecase(ntunnel[nrs], rstunnel[nrs]); if (dblebuf) { dessinecase(ntunnel[!nrs], rstunnel[!nrs]); } ntunnel[nrs] = 0; gerepouvoirs(); dessinebande(); rafraichit(); if (preums) { if (!dblebuf) { restorepalette(pal, 60); } preums = 0; } if (enpause == 1) { pauseifie(); } } while(encore && clavier[SDLK_ESCAPE] != SDL_PRESSED && clavier[SDLK_F8] != SDL_PRESSED); if (Mix_PlayingMusic) { Mix_HaltMusic(); } #ifdef DEBUG /*--Faisons un peu de statistiques sur les performances--*/ for (i=0; iVITESSE) { nral++; } } moy /= (float)nstat; printf("Statistiques sur %i rafraichissements d'écran:\n", nstat); printf("%.2f frames par seconde en moyenne, ", 1000/moy); printf("limitées par le maximum de %i fps\n", 1000/VITESSE); printf("%i frame%s(%.2f%%) étai%st au-delà du maximum.\n", nral, nral>1 ? "s " : " ", (100.0*nral)/nstat, nral>1 ? "en" : ""); #endif reinit(); SDL_FreeSurface(bande); // if (!encore) bruitsplus(s_fin, 1); if (clavier[SDLK_F8] == SDL_PRESSED) { while(clavier[SDLK_F8] == SDL_PRESSED) { SDL_PumpEvents(); clavier = SDL_GetKeyState(NULL); } detruit_sprites(); return 2; } else if (clavier[SDLK_ESCAPE] == SDL_PRESSED) { while(clavier[SDLK_ESCAPE] == SDL_PRESSED) { SDL_PumpEvents(); clavier=SDL_GetKeyState(NULL); } return 0; } else { return 1; } } /*--Initialisation de chaque partie--*/ int initpartie(void) { int i; FILE *niveau; //x char chemin[256]; char chemin[MAX_STRING_LENGTH]; //x char nomniveau[256]; char nomniveau[MAX_STRING_LENGTH]; int ret; enpause = 0; if (!choisi) { do { ret = choix("choix.niv", "Choix.bmp"); } while (ret == 2); if (ret == 1) { return 0; } } i = aleat(nb_niveaux); strcpy(nomniveau, niveaux[i]); //printf("C'est parti : niveau %s [%i/%i].\n", nomniveau, i, nb_niveaux); videcran(); reinit(); detruit_sprites(); couleurs = charge_sprite("infos.spr", decl); sprintf(chemin, "%s/%s", prefixeniv, nomniveau); niveau = fopen(chemin, "r"); if (niveau == NULL) { errormessage("Impossible d'ouvrir le niveau", nomniveau); } sprintf(chemin, "%s/Bande.bmp", prefixeimg); bande = SDL_LoadBMP(chemin); if (bande == NULL) { errormessage("Impossible de charger l'image", chemin); } SDL_SetColors(ecran, bande->format->palette->colors, decl, bande->format->palette->ncolors); decl += bande->format->palette->ncolors; charge_graphs(niveau); charge_sprites(sprit, spritliste, NB_PERSO); for (i = 0; i < NB_PERSO; i++) { initperso(i); } //x chargeniv(niveau); // P.K. animsfin = NULL; // no animation freeplan(&plan); chargeniv_dynamic(niveau, &plan, 1, danslemenu, 1); fclose(niveau); dessinebande(); if (Mix_PlayingMusic) { Mix_HaltMusic(); } //if (avecmusique) Mix_PlayMusic(muschoix, -1); return jeu(); } /*--Fin d'un round, affichage du score...--*/ int fin(int ret) { int matchfini=0; int i, j; int a, r, p; int n=-1; // nobody wins //x char texte[8][20], chemin[256], nom[256]; char texte[8][20], chemin[MAX_STRING_LENGTH], nom[MAX_STRING_LENGTH]; int ord; Coord middle; SDL_Rect g; Sprite *gagnant; middle.x = (resolution.plan_width+64)/2; //xx middle.x = resolution.window_width/2; middle.y = (resolution.plan_height-40*NB_PERSO)/2; //xx middle.y = (resolution.window_height-40*NB_PERSO)/2; g.w = g.h = 32; //x g.x=(640-32)/2; g.y=(480-40*NB_PERSO)/2; g.x = resolution.x_offset+middle.x; g.y = resolution.y_offset+middle.y; videcran(); if (changepersos) { choisi=0; } if (!ret) { return 1; } for (i=0; i= sprit[n]->nanims ? BAS : GAGNE; r=3; p=1; if (modejeu == MODE_STD) { score[n]++; } } for (i=0; i= 16) { for (j=0; jscore[i]-15) { score[j]-=score[i]-15; } else { score[j]=0; } } for (i=0; i=0; i--) { //x ord = 440-40*(NB_PERSO-i-1); //x ord = resolution.plan_height-40*(NB_PERSO-i); //x ord = resolution.window_height-40*(NB_PERSO-i); ord = resolution.window_height-resolution.y_offset-40*(NB_PERSO-i); blitsprit(sprit[i], BAS, 0, 64-resolution.x_offset, ord); for (j=0; janims[a]->nframes*r+p; i++) { SDL_PumpEvents(); SDL_FillRect(ecran, &g, 0); if (strcmp(gagnant->nom,"Magus")) { // Le gagnant n'est pas Magus //x blitsprit(gagnant, a, i%gagnant->anims[a]->nframes, g.x, g.y); blitsprit(gagnant, a, i%gagnant->anims[a]->nframes, middle.x, middle.y); } else { /* C'est un bricolage pour l'anim de Magus */ int u = i/2; if (u >= 14) { u = (u < 22) ? (6 + u%2) : (u - 8); } if (u < gagnant->anims[a]->nframes) { //x blitsprit(gagnant, a, u, g.x, g.y); blitsprit(gagnant, a, u, middle.x, middle.y); } } SDL_Flip(ecran); SDL_Delay(70); } SDL_Delay(500); /* Match fini ? */ for (i=0, n=0; iscore[n]) { n=i; } } if (score[n] >= NROUNDS) { matchfini=1; for (i=0; iscore[n]-1-pointdavance && i!=n) { matchfini = 0; } } if (matchfini) { videcran(); sprintf(nom, "%s", sprit[n]->nom); nom[0]=toupper(nom[0]); // printf("Gagnant joueur %i, personnage %s.\n", n+1, sprit[n]->nom); printf("Gagnant joueur %i, personnage %s.\n", n+1, nom); // strcpy(texte[0], sprit[n]->nom); strcpy(texte[0], nom); for (j=1; j<7; j++) { strcpy(texte[j],"\0"); } sprintf(texte[7], "Wins !!!"); // sprintf(chemin, "%s.bmp", sprit[n]->nom); sprintf(chemin, "%s.bmp", nom); ecrantexte(texte, chemin, 8, 0); } } detruit_sprites(); clavier=SDL_GetKeyState(NULL); if (matchfini) { return 1; } if (clavier[SDLK_SPACE] == SDL_PRESSED) { while(clavier[SDLK_SPACE] == SDL_PRESSED) { SDL_PumpEvents(); clavier=SDL_GetKeyState(NULL); } return 2; } else if (clavier[SDLK_ESCAPE] == SDL_PRESSED) { while(clavier[SDLK_ESCAPE] == SDL_PRESSED) { SDL_PumpEvents(); clavier = SDL_GetKeyState(NULL); } return 1; } return 2; } int main(int argc, char **argv) { int i; int ret; int canal; //x char textecr[8][20], chemin[256]; char textecr[8][20], chemin[MAX_STRING_LENGTH]; /* Various languages localization */ setlocale (LC_MESSAGES, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); chargeconfig(); sprintf(prefixeniv, "%s/Niveaux", repertoire); sprintf(prefixeimg, "%s/Decors", repertoire); sprintf(prefixespr, "%s/Sprites", repertoire); sprintf(prefixeson, "%s/Bruitages", repertoire); VITESSE=1000/VITESSE; //x P.K. spritliste=(char **)calloc(8, sizeof(char *)); spritliste=(char **)calloc(MAX_NPERSO, sizeof(char *)); //x P.K. for (i=0; i<8; i++) for (i=0; i