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