1 //      (_||_/
2 //      (    )       Classe Sprite
3 //     ( o  0 )
4 //-OOO�--(_)---�OOO---------------------------------------
5 //                   Copyright (C) 2006 By Dominique Roux-Serret
6 // .OOOo      oOOO.  roux-serret@ifrance.com
7 //-(   )------(   )---------------------------------------
8 //  ( (        ) /   Le 11/01/2006
9 //   (_)      (_/
10 
11 //    This program is free software; you can redistribute it and/or modify
12 //    it under the terms of the GNU General Public License as published by
13 //    the Free Software Foundation; either version 2 or version 3 of the License.
14 
15 //    This program is distributed in the hope that it will be useful,
16 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
17 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 //    GNU General Public License for more details.
19 
20 //    You should have received a copy of the GNU General Public License along
21 //    with this program; if not, write to the Free Software Foundation, Inc.,
22 //    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 
24 #include <iostream>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <math.h>
29 #include "sprite.h"
30 #include "preference.h"
31 #include "utils.h"
32 
33 /*** Variables Globales ***/
34 /**************************/
35 extern SDL_Surface *sdlVideo;
36 extern SDL_VideoInfo *sdlVideoInfo;
37 extern Uint32 FontColor;
38 extern Sprite *Sprites;
39 extern int NSprites;
40 extern sPreference Pref;
41 
42 static char* OrdreTexte="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-!?*+<>%$()&;";
43 static char* OrdreTexte2="abcdefghijklmnopqrstuvwxyz0123456789,_|?*+<>%$[]&;";
44 static int TableTexte[256];
45 
46 char Langue[31][16]; // M�morise les noms des langues
47 int NTextes=0;
48 bool AfficheC=false; // Si peut afficher le chargeur lors du chargement
49 
50 #define N_SPRITESFOND 2
51 
52 /*** Affiche le chargeur lors du chargement ***/
53 /**********************************************/
AfficheChargeur()54 void AfficheChargeur()
55 {
56   static int NumAf=-1; // Num�ro su sprite affich�
57   int i,Old;
58   int Hor;
59 
60   if(AfficheC==true) {
61     Hor=SDL_GetTicks();
62     i=(Hor/(1000/25))%Sprites[chargeur].N; // Calcule le num�ro su sprite � afficher
63 
64     if(i!=NumAf) {
65       Old=NumAf;
66       NumAf=i;
67       Sprites[chargeur].Affiche(400,300,NumAf);
68       SDL_Flip(sdlVideo);
69       if(Old!=-1) Sprites[chargeur].Efface(400,300,Old,sdlVideo);
70     }
71   }
72 
73 }
74 
75 /*** Charge les Sprites d'une langue ***/
76 /***************************************/
LoadLangue()77 bool LoadLangue()
78 {
79   long L,P;
80   int i;
81   unsigned char *Buf;
82   char PathFile[512];
83 
84   strcpy(PathFile,Langue[Pref.Langue]);
85   GetPath(PathFile);
86   if(FileExiste(PathFile)==false) {
87     std::cerr <<"Impossible de trouver "<<Langue[Pref.Langue]<<std::endl;
88     return false;
89   }
90   L=ChargeFichier(PathFile,Buf);
91 
92   // Lit les sprites
93   P=0;
94   for(i=0;i<NTextes;i++) {
95     if(Sprites[T_level+i].N) Sprites[T_level+i].Delete();
96     if(Sprites[T_level+i].Load(Buf,P)==false) return false;
97   }
98   delete [] Buf; // Lib�re la m�moire du fichier des sprites
99 
100   return true;
101 }
102 
103 /*** Charge les Sprites du jeu ***/
104 /*********************************/
LoadSprites()105 bool LoadSprites()
106 {
107   long L,P;
108   int i;
109   unsigned char *Buf;
110   int NSp;
111 
112   char PathFile[512]="language.dat";
113   GetPath(PathFile);
114 
115   // Initialise la table de caractaire des textes
116   for(i=0;i<256;i++) TableTexte[i]=-1;
117   i=0;
118   while(OrdreTexte[i]!=0) {
119     TableTexte[(int)(OrdreTexte[i])]=i;
120     i++;
121   }
122   i=0;
123   while(OrdreTexte2[i]!=0) {
124     TableTexte[(int)(OrdreTexte2[i])]=i;
125     i++;
126   }
127 
128   // *** Charge le fichier des langues ***
129   // *************************************
130   if(FileExiste(PathFile)==false) {
131     std::cerr <<"Impossible de trouver 'language.dat'"<<std::endl;
132     return false;
133   }
134   L=ChargeFichier(PathFile,Buf);
135 
136   // Prend le nombre de sprites
137   NSp=(int)(Buf[0])*256+(int)(Buf[1]);
138   NSp+=N_SPRITESFOND+2;
139   NTextes=(int)(Buf[2])*256+(int)(Buf[3]);
140   Pref.NLangues=(int)(Buf[4])*256+(int)(Buf[5]);
141 
142   NSprites=NSp+NTextes+Pref.NLangues;
143   Sprites=new Sprite[NSprites];
144 
145   // R�cup�re les nom des langues
146   P=6;
147   for(i=0;i<Pref.NLangues;i++) {
148     strcpy(Langue[i],(char*)(Buf+P));
149     P+=strlen((char*)(Buf+P))+1;
150   }
151 
152   // Charge les sprites des langues
153   for(i=0;i<Pref.NLangues;i++)
154     if(Sprites[T_Langue+i].Load(Buf,P)==false) return false;
155 
156   if(Sprites[chargeur].Load(Buf,P)==false) return false; // Sprite du chargeur
157   AfficheC=true; // Peut afficher le sprite du chargeur
158 
159   delete [] Buf;
160 
161   // *** Charge le fichier des sprites ***
162   // *************************************
163   strcpy(PathFile,"sprites.dat");
164   GetPath(PathFile);
165   if(FileExiste(PathFile)==false) {
166     std::cerr <<"Impossible de trouver 'sprites.dat'"<<std::endl;
167     return false;
168   }
169   L=ChargeFichier(PathFile,Buf);
170 
171   // Lit les sprites
172   P=0;
173   for(i=0;i<NSp;i++) {
174     AfficheChargeur();
175     switch(i) {
176     case fjeu:
177     case fmenu:
178       if(Sprites[i].Nouveau(800,600)==false) return false;
179       break;
180     case corde:
181       Sprites[i].N=0;
182       break;
183     case chargeur:
184       break;
185     default:
186       if(Sprites[i].Load(Buf,P)==false) return false;
187     }
188   }
189 
190   delete [] Buf; // Lib�re la m�moire du fichier des sprites
191 
192   // *** Charge la langue ***
193   // ************************
194   if(Pref.Langue!=-1) LoadLangue();
195 
196   AfficheC=false; // N'affiche plus les sprites du chargeur
197   return true;
198 }
199 
200 /*** Retourne la longueur d'un nombre ***/
201 /****************************************/
LongueurChiffre(int C)202 int LongueurChiffre(int C)
203 {
204   int l=0;
205 
206   do {
207     l+=Sprites[chiffres].Dim[(C%10)].L;
208     C/=10;
209     if(C) l+=ECART_ENTRE_CHIFFRE;
210   } while(C);
211 
212   return l;
213 }
214 
215 /*** Retourne la longueur d'un texte ***/
216 /***************************************/
LongueurString(char * Texte)217 int LongueurString(char *Texte)
218 {
219   int i=0;
220   int l=0;
221   int Le;
222 
223   while(Texte[i]!=0) {
224     Le=(int)(Texte[i]);
225     if(TableTexte[Le]!=-1) {
226       l+=Sprites[lettres].Dim[(TableTexte[Le])].L;
227       if(Texte[i+1]!=0) l+=ECART_ENTRE_LETTRE;
228     }
229     else {
230       if(Le==(int)(' ')) l+=LONGUEUR_ESPACE;
231     }
232 
233     i++;
234   }
235 
236   return l;
237 }
238 
239 /*** Test si un caracataire existe ***/
240 /*************************************/
CharExiste(char C)241 bool CharExiste(char C)
242 {
243   if(C==' ') return true;
244   if(TableTexte[(int)(C)]!=-1) return true;
245   return false;
246 }
247 /*** Affiche un nombre ***/
248 /*************************/
AfficheChiffre(int x,int y,int Nombre,SDL_Surface * Fond)249 void AfficheChiffre(int x,int y,int Nombre,SDL_Surface *Fond)
250 {
251   int l=LongueurChiffre(Nombre);
252 
253   x+=l/2;
254   do {
255     Sprites[chiffres].Affiche(x-(Sprites[chiffres].Dim[(Nombre%10)].L)/2,y,Nombre%10,Fond);
256     x-=Sprites[chiffres].Dim[(Nombre%10)].L+ECART_ENTRE_CHIFFRE;
257     Nombre/=10;
258   } while(Nombre);
259 
260 }
261 
262 /*** Affiche un Texte ***/
263 /************************/
AfficheString(int x,int y,char * Texte,SDL_Surface * Fond)264 void AfficheString(int x,int y,char *Texte,SDL_Surface *Fond)
265 {
266   int i=0;
267   int Le;
268 
269   while(Texte[i]!=0) {
270     Le=(int)(Texte[i]);
271 
272     if(TableTexte[Le]!=-1) { // Si un caractaire connue
273       Le=TableTexte[Le];
274       Sprites[lettres].Affiche(x+(Sprites[lettres].Dim[Le].L/2),y,Le,Fond);
275       x+=Sprites[lettres].Dim[Le].L+ECART_ENTRE_LETTRE;
276     }
277     else { // Si un espace
278       if(Le==(int)(' ')) x+=LONGUEUR_ESPACE-ECART_ENTRE_LETTRE;
279     }
280 
281     i++;
282   }
283 }
284 
285 /*** Efface un nombre ***/
286 /************************/
EffaceChiffre(int x,int y,int Nombre,SDL_Surface * Fond)287 void EffaceChiffre(int x,int y,int Nombre,SDL_Surface *Fond)
288 {
289   int l=LongueurChiffre(Nombre);
290   int h=Sprites[chiffres].Dim[0].H;
291 
292   if(!Fond) Fond=Sprites[fjeu].Image[0];
293   Sprites[chiffres].EffaceCarre(x-l/2,y-h/2,x+l/2,y+h/2,Fond);
294 }
295 
296 /*** Affiche un text dans la langue ***/
297 /**************************************/
AfficheText(int x,int y,e_Sprite Text,SDL_Surface * Fond)298 void AfficheText(int x,int y,e_Sprite Text,SDL_Surface *Fond)
299 {
300   Sprites[Text].Affiche(x,y,0,Fond);
301 }
302 
303 /*** Constructeur ***/
304 /********************/
Sprite(void)305 Sprite::Sprite(void) : N(0), Image(NULL), Dim(NULL)
306 { }
307 
~Sprite(void)308 Sprite::~Sprite(void)
309 {
310   if(N) {
311     for(int i=0;i<N;i++) {
312       SDL_FreeSurface(Image[i]);
313     }
314     delete [] Image;
315     delete [] Dim;
316   }
317 }
318 
319 /*** Charge les sprites ***/
320 /**************************/
Load(unsigned char * Buf,long & P)321 bool Sprite::Load(unsigned char *Buf,long &P)
322 {
323   int i,j;
324   unsigned char *B;
325   unsigned long ul=1; // test le type de processeur
326   unsigned char *pul=(unsigned char*)(&ul) ;
327 
328   // Prend nombre de sprites
329   N=(int)(Buf[P])*256+(int)(Buf[P+1]);
330   P+=2;
331   Dim=new s_Dim[N];
332   Image=new SDL_Surface* [N];
333 
334   // Lit tous les sprites
335   for(i=0;i<N;i++) {
336     // Affiche l'animation de chargement
337     AfficheChargeur();
338 
339     // Lit les dimensions
340     Dim[i].L=(int)(Buf[P])*256+(int)(Buf[P+1]);
341     P+=2;
342     Dim[i].H=(int)(Buf[P])*256+(int)(Buf[P+1]);
343     P+=2;
344     Dim[i].cx=(int)(Buf[P])*256+(int)(Buf[P+1]);
345     P+=2;
346     Dim[i].cy=(int)(Buf[P])*256+(int)(Buf[P+1]);
347     P+=2;
348     Dim[i].bpp=(int)(Buf[P])*256+(int)(Buf[P+1]);
349     P+=2;
350 
351     // Fabrique la surface
352     Image[i]=SDL_CreateRGBSurface((Dim[i].bpp-3)*SDL_SRCALPHA,Dim[i].L,Dim[i].H,Dim[i].bpp*8,
353 				  0xff,0xff00,0xff0000,0xff000000*(Dim[i].bpp-3));
354     if(Image[i]==NULL) {
355       std::cerr <<"Impossible de cr�er une Surface SDL!"<<std::endl;
356       return false;
357     }
358 
359     // Copie les pixels
360     SDL_LockSurface(Image[i]);
361     B=(unsigned char*)Image[i]->pixels;
362 
363     if(pul[0]==0) { // Processeur type Power PC, 68000, ..
364       for(j=0;j<Dim[i].L*Dim[i].H*Dim[i].bpp;j+=Dim[i].bpp) {
365 	if(Dim[i].bpp==4) B[j+3]=Buf[P++];
366 	B[j+2]=Buf[P++];
367 	B[j+1]=Buf[P++];
368 	B[j]=Buf[P++];
369       }
370     }
371     else
372       for(j=0;j<Dim[i].L*Dim[i].H*Dim[i].bpp;j++) B[j]=Buf[P++];
373 
374     SDL_UnlockSurface(Image[i]);
375 
376     // Si peut la mettre en surface Hardware
377     if(sdlVideoInfo->blit_hw_A) {
378       SDL_Surface *Provi=SDL_ConvertSurface(Image[i],Image[i]->format,SDL_HWSURFACE);
379       SDL_FreeSurface(Image[i]);
380       Image[i]=Provi;
381     }
382   }
383 
384   return true;
385 }
386 
387 /*** Affiche le sprite ***/
388 /*************************/
Affiche(int X,int Y,int NumSpr,SDL_Surface * Fond)389 void Sprite::Affiche(int X,int Y,int NumSpr,SDL_Surface *Fond)
390 {
391   SDL_Rect Position;
392   SDL_Rect Di;
393 
394   Position.x=X-Dim[NumSpr].cx;
395   Position.y=Y-Dim[NumSpr].cy;
396 
397   Position.w=Position.h=Di.x=Di.y=0;
398   Di.w=Dim[NumSpr].L;
399   Di.h=Dim[NumSpr].H;
400 
401   if(Fond==NULL) Fond=sdlVideo;
402 
403   SDL_BlitSurface(Image[NumSpr],&Di,Fond,&Position);
404 }
405 
406 /*** Affiche un bout du sprite ***/
407 /*********************************/
AfficheCorde(int dx,int dy,int fx,int fy)408 void Sprite::AfficheCorde(int dx,int dy,int fx,int fy)
409 {
410   float d;
411   float lx=float(fx-dx);
412   float ly=float(fy-dy);
413   int P,n,i,j;
414   unsigned char *B;
415   float x=dx;
416   float y=dy;
417 
418   d=sqrt(lx*lx+ly*ly); // Longueur de la corde
419   if( (float)((int)(d))!=d ) n=(int)(d)+1; // Met en nombre de point
420   else n=(int)d;
421 
422   // Trace la ligne
423   SDL_LockSurface(sdlVideo);
424   B=(unsigned char*)sdlVideo->pixels;
425 
426   lx=lx/(float)n;
427   ly=ly/(float)n;
428 
429   for(i=0;i<=n;i++) {
430     P=((int)(x)+(int)(y)*800)*sdlVideo->format->BytesPerPixel;
431     for(j=0;j<sdlVideo->format->BytesPerPixel;j++) B[P+j]=255;
432     x+=lx;
433     y+=ly;
434   }
435 
436   SDL_UnlockSurface(sdlVideo);
437 }
438 
439 /*** Efface le sprite ***/
440 /************************/
Efface(int X,int Y,int NumSpr,SDL_Surface * Fond)441 void Sprite::Efface(int X,int Y,int NumSpr,SDL_Surface *Fond)
442 {
443   SDL_Rect Position;
444 
445   Position.w=Dim[NumSpr].L;
446   Position.h=Dim[NumSpr].H;
447   Position.x=X-Dim[NumSpr].cx;
448   Position.y=Y-Dim[NumSpr].cy;
449   SDL_BlitSurface(Fond,&Position,sdlVideo,&Position);
450 }
451 
452 /*** Efface un carr� � l'ecran ***/
453 /*********************************/
EffaceCarre(int dx,int dy,int fx,int fy,SDL_Surface * Fond)454 void Sprite::EffaceCarre(int dx,int dy,int fx,int fy,SDL_Surface *Fond)
455 {
456   int p;
457   SDL_Rect Position;
458 
459   if(dx>fx) { p=dx; dx=fx; fx=p; }
460   if(dy>fy) { p=dy; dy=fy; fy=p; }
461 
462   Position.w=fx-dx+1;
463   Position.h=fy-dy+1;
464   Position.x=dx;
465   Position.y=dy;
466   SDL_BlitSurface(Fond,&Position,sdlVideo,&Position);
467 }
468 
469 /*** Alloue un nouveau sprite vide ***/
470 /*************************************/
Nouveau(int Lx,int Ly)471 bool Sprite::Nouveau(int Lx,int Ly)
472 {
473   Delete(); // Efface au cas ou
474 
475   N=1;
476   Dim=new s_Dim[N];
477   Image=new SDL_Surface* [N];
478 
479   Dim[0].L=Lx;
480   Dim[0].H=Ly;
481   Dim[0].cx=Lx/2;
482   Dim[0].cy=Ly/2;
483   Dim[0].bpp=3; // Pas de transparence
484 
485   // Fabrique la surface
486   Image[0]=SDL_CreateRGBSurface((Dim[0].bpp-3)*SDL_SRCALPHA,Dim[0].L,Dim[0].H,Dim[0].bpp*8,
487 				0xff,0xff00,0xff0000,0xff000000*(Dim[0].bpp-3));
488   if(Image[0]==NULL) {
489     std::cerr <<"Impossible de cr�er une Surface SDL!"<<std::endl;
490     return false;
491   }
492   return true;
493 }
494 
495 /*** Efface le sprite ***/
496 /************************/
Delete(void)497 void Sprite::Delete(void)
498 {
499   if(N) {
500     for(int i=0;i<N;i++) {
501       SDL_FreeSurface(Image[i]);
502     }
503     delete [] Image;
504     delete [] Dim;
505     N=0;
506   }
507 }
508