]> git.jsancho.org Git - lugaru.git/blob - Source/Sprite.cpp
rename for readability
[lugaru.git] / Source / Sprite.cpp
1 /*
2 Copyright (C) 2003, 2010 - Wolfire Games
3
4 This file is part of Lugaru.
5
6 Lugaru is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
14
15 See the GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 */
21
22 #include "Sprite.h"
23 #include "Person.h"
24 #include "Game.h"
25 extern XYZ viewer;
26 extern float viewdistance;
27 extern float fadestart;
28 extern int environment;
29 extern float texscale;
30 extern Light light;
31 extern float multiplier;
32 extern float gravity;
33 extern Terrain terrain;
34 extern Objects objects;
35 extern int detail;
36 extern XYZ viewerfacing;
37 extern int bloodtoggle;
38 extern XYZ windvector;
39
40 // init statics
41 Texture Sprite::cloudtexture;
42 Texture Sprite::cloudimpacttexture;
43 Texture Sprite::bloodtexture;
44 Texture Sprite::flametexture;
45 Texture Sprite::bloodflametexture;
46 Texture Sprite::smoketexture;
47 Texture Sprite::snowflaketexture;
48 Texture Sprite::shinetexture;
49 Texture Sprite::splintertexture;
50 Texture Sprite::leaftexture;
51 Texture Sprite::toothtexture;
52
53 float Sprite::checkdelay = 0;
54
55 vector<Sprite*> Sprite::sprites = vector<Sprite*>();
56
57 //Functions
58 void Sprite::Draw()
59 {
60         int i,j,k;
61         static float M[16];
62         static XYZ point;
63         static float distancemult;
64         static int lasttype;
65         static int lastspecial;
66         static int whichpatchx,whichpatchz;
67         static XYZ start,end,colpoint;
68         static bool check;
69         static bool blend;
70         static float tempmult;
71         static XYZ difference;
72         static float lightcolor[3];
73         static float viewdistsquared=viewdistance*viewdistance;
74         static XYZ tempviewer;
75
76         tempviewer=viewer+viewerfacing*6;
77         check=0;
78
79         lightcolor[0]=light.color[0]*.5+light.ambient[0];
80         lightcolor[1]=light.color[1]*.5+light.ambient[1];
81         lightcolor[2]=light.color[2]*.5+light.ambient[2];
82
83         checkdelay-=multiplier*10;
84
85         if(checkdelay<=0){
86                 check=1;
87                 checkdelay=1;
88         }
89
90         lasttype=-1;
91         lastspecial=-1;
92         glEnable(GL_BLEND);
93         glDisable(GL_LIGHTING);
94         glDisable(GL_CULL_FACE);
95         glEnable(GL_TEXTURE_2D);
96         blend = 1;
97         glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
98         glDepthMask(0);
99         glAlphaFunc(GL_GREATER, 0.0001);
100         for(i=0;i<sprites.size();i++){
101                 if(lasttype!=sprites[i]->type) {
102                         switch(sprites[i]->type) {
103                                 case cloudsprite:
104                                         cloudtexture.bind();
105                                         if(!blend){
106                                                 blend=1;
107                                                 glAlphaFunc(GL_GREATER, 0.0001);
108                                                 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
109                                         }
110                                 break;
111                                 case cloudimpactsprite:
112                                         cloudimpacttexture.bind();
113                                         if(!blend){
114                                                 blend=1;
115                                                 glAlphaFunc(GL_GREATER, 0.0001);
116                                                 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
117                                         }
118                                 break;
119                                 case breathsprite:
120                                         cloudimpacttexture.bind();
121                                         if(!blend){
122                                                 blend=1;
123                                                 glAlphaFunc(GL_GREATER, 0.0001);
124                                                 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
125                                         }
126                                 break;
127                                 case smoketype:
128                                         smoketexture.bind();
129                                         if(!blend){
130                                                 blend=1;
131                                                 glAlphaFunc(GL_GREATER, 0.0001);
132                                                 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
133                                         }
134                                 break;
135                                 case bloodsprite:
136                                         bloodtexture.bind();
137                                         if(!blend){
138                                                 blend=1;
139                                                 glAlphaFunc(GL_GREATER, 0.0001);
140                                                 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
141                                         }
142                                 break;
143                                 case splintersprite :
144                                         if(lastspecial!=sprites[i]->special) {
145                                                 if(sprites[i]->special==0)splintertexture.bind();
146                                                 if(sprites[i]->special==1)leaftexture.bind();
147                                                 if(sprites[i]->special==2)snowflaketexture.bind();
148                                                 if(sprites[i]->special==3)toothtexture.bind();
149                                                 if(!blend){
150                                                         blend=1;
151                                                         glAlphaFunc(GL_GREATER, 0.0001);
152                                                         glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
153                                                 }
154                                         }
155                                 break;
156                                 case snowsprite:
157                                         snowflaketexture.bind();
158                                         if(!blend){
159                                                 blend=1;
160                                                 glAlphaFunc(GL_GREATER, 0.0001);
161                                                 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
162                                         }
163                                 break;
164                                 case weaponshinesprite:
165                                         shinetexture.bind();
166                                         if(blend){
167                                                 blend=0;
168                                                 glAlphaFunc(GL_GREATER, 0.001);
169                                                 glBlendFunc(GL_SRC_ALPHA,GL_ONE);
170                                         }
171                                 break;
172                                 case flamesprite:
173                                 case weaponflamesprite:
174                                         flametexture.bind();
175                                         if(blend||lasttype==bloodflamesprite){
176                                                 blend=0;
177                                                 glAlphaFunc(GL_GREATER, 0.3);
178                                                 glBlendFunc(GL_SRC_ALPHA,GL_ONE);
179                                         }
180                                 break;
181                                 case bloodflamesprite:
182                                         bloodflametexture.bind();
183                                         if(blend){
184                                                 blend=0;
185                                                 glAlphaFunc(GL_GREATER, 0.3);
186                                                 glBlendFunc(GL_ONE,GL_ZERO);
187                                         }
188                                 break;
189                         }
190                 }
191                 if(sprites[i]->type==snowsprite)
192                         distancemult=(144-(distsq(&tempviewer,&sprites[i]->position)-(144*fadestart))*(1/(1-fadestart)))/144;
193                 else
194                         distancemult=(viewdistsquared-(distsq(&viewer,&sprites[i]->position)-(viewdistsquared*fadestart))*(1/(1-fadestart)))/viewdistsquared;
195                 if(sprites[i]->type==flamesprite){
196                         if(distancemult>=1) glColor4f(sprites[i]->color[0],sprites[i]->color[1],sprites[i]->color[2],sprites[i]->opacity);
197                         else glColor4f(sprites[i]->color[0],sprites[i]->color[1],sprites[i]->color[2],sprites[i]->opacity*distancemult);
198                 } else {
199                         if(distancemult>=1) glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],sprites[i]->opacity);
200                         else glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],sprites[i]->opacity*distancemult);
201                 }
202                 lasttype=sprites[i]->type;
203                 lastspecial=sprites[i]->special;
204                 glMatrixMode(GL_MODELVIEW);                                                     // Select The Modelview Matrix
205                 glPushMatrix();
206                         glTranslatef(sprites[i]->position.x,sprites[i]->position.y,sprites[i]->position.z);
207                         if((sprites[i]->type==flamesprite||sprites[i]->type==weaponflamesprite||sprites[i]->type==weaponshinesprite)){
208                                 difference=viewer-sprites[i]->position;
209                                 Normalise(&difference);
210                                 glTranslatef(difference.x*sprites[i]->size/4, difference.y*sprites[i]->size/4, difference.z*sprites[i]->size/4);
211                         }
212                         if(sprites[i]->type==snowsprite){
213                                 glRotatef(sprites[i]->rotation*.2,0,.3,1);
214                                 glTranslatef(1,0,0);
215                         }
216                         glGetFloatv(GL_MODELVIEW_MATRIX,M);
217                         point.x=M[12];
218                         point.y=M[13];
219                         point.z=M[14];
220                         glLoadIdentity();
221                         glTranslatef(point.x, point.y, point.z);
222
223                         glRotatef(sprites[i]->rotation,0,0,1);
224
225                         if((sprites[i]->type==flamesprite||sprites[i]->type==weaponflamesprite||sprites[i]->type==weaponshinesprite||sprites[i]->type==bloodflamesprite)){
226                                 if(sprites[i]->alivetime<.14)glScalef(sprites[i]->alivetime/.14,sprites[i]->alivetime/.14,sprites[i]->alivetime/.14);
227                         }
228                         if(sprites[i]->type==smoketype||sprites[i]->type==snowsprite||sprites[i]->type==weaponshinesprite||sprites[i]->type==breathsprite){
229                                 if(sprites[i]->alivetime<.3){
230                                         if(distancemult>=1)glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],sprites[i]->opacity*sprites[i]->alivetime/.3);
231                                         if(distancemult<1)glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],sprites[i]->opacity*distancemult*sprites[i]->alivetime/.3);
232                                 }
233                         }
234                         if(sprites[i]->type==splintersprite&&sprites[i]->special>0&&sprites[i]->special!=3){
235                                 if(sprites[i]->alivetime<.2){
236                                         if(distancemult>=1) glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],sprites[i]->alivetime/.2);
237                                         else glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],distancemult*sprites[i]->alivetime/.2);
238                                 }
239                                 else {
240                                         if(distancemult>=1) glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],1);
241                                         else glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],1);
242                                 }
243                         }
244                         if(sprites[i]->type==splintersprite&&(sprites[i]->special==0||sprites[i]->special==3)){
245                                 if(distancemult>=1) glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],1);
246                                 else glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],1);
247                         }
248
249                         glBegin(GL_TRIANGLES);
250                         glTexCoord2f(1.0f, 1.0f); glVertex3f( .5*sprites[i]->size, .5*sprites[i]->size, 0.0f);
251                         glTexCoord2f(0.0f, 1.0f); glVertex3f(-.5*sprites[i]->size, .5*sprites[i]->size, 0.0f);
252                         glTexCoord2f(1.0f, 0.0f); glVertex3f( .5*sprites[i]->size,-.5*sprites[i]->size, 0.0f);
253                         glTexCoord2f(0.0f, 0.0f); glVertex3f(-.5*sprites[i]->size,-.5*sprites[i]->size, 0.0f);
254                         glTexCoord2f(1.0f, 0.0f); glVertex3f( .5*sprites[i]->size, -.5*sprites[i]->size, 0.0f);
255                         glTexCoord2f(0.0f, 1.0f); glVertex3f(-.5*sprites[i]->size, .5*sprites[i]->size, 0.0f);
256                         glEnd();
257                 glPopMatrix();
258         }
259         tempmult=multiplier;
260         for(i=sprites.size()-1;i>=0;i--){
261                 multiplier=tempmult;
262                 if(sprites[i]->type!=snowsprite) {
263                         sprites[i]->position+=sprites[i]->velocity*multiplier;
264                         sprites[i]->velocity+=windvector*multiplier;
265                 }
266                 if(sprites[i]->type==flamesprite||sprites[i]->type==smoketype)sprites[i]->position+=windvector*multiplier/2;
267                 if((sprites[i]->type==flamesprite||sprites[i]->type==weaponflamesprite||sprites[i]->type==weaponshinesprite||sprites[i]->type==bloodflamesprite))
268                         multiplier*=sprites[i]->speed*.7;
269                 sprites[i]->alivetime+=multiplier;
270
271                 if(sprites[i]->type==cloudsprite||sprites[i]->type==cloudimpactsprite){
272                         sprites[i]->opacity-=multiplier/2;
273                         sprites[i]->size+=multiplier/2;
274                         sprites[i]->velocity.y+=gravity*multiplier*.25;
275                 }
276                 if(sprites[i]->type==breathsprite){
277                         sprites[i]->opacity-=multiplier/2;
278                         sprites[i]->size+=multiplier/2;
279                         if(findLength(&sprites[i]->velocity)<=multiplier)sprites[i]->velocity=0;
280                         else{
281                                 XYZ slowdown;
282                                 slowdown=sprites[i]->velocity*-1;
283                                 Normalise(&slowdown);
284                                 slowdown*=multiplier;
285                                 sprites[i]->velocity+=slowdown;
286                         }
287                 }
288                 if(sprites[i]->type==snowsprite){
289                         sprites[i]->size-=multiplier/120;
290                         sprites[i]->rotation+=multiplier*360;
291                         sprites[i]->position.y-=multiplier;
292                         sprites[i]->position+=windvector*multiplier;
293                         if(sprites[i]->position.y<tempviewer.y-6)sprites[i]->position.y+=12;
294                         if(sprites[i]->position.y>tempviewer.y+6)sprites[i]->position.y-=12;
295                         if(sprites[i]->position.z<tempviewer.z-6)sprites[i]->position.z+=12;
296                         if(sprites[i]->position.z>tempviewer.z+6)sprites[i]->position.z-=12;
297                         if(sprites[i]->position.x<tempviewer.x-6)sprites[i]->position.x+=12;
298                         if(sprites[i]->position.x>tempviewer.x+6)sprites[i]->position.x-=12;
299                 }
300                 if(sprites[i]->type==bloodsprite){
301                         bool spritehit=0;
302                         sprites[i]->rotation+=multiplier*100;
303                         sprites[i]->velocity.y+=gravity*multiplier;
304                         if(check){
305                                 XYZ where,startpoint,endpoint,movepoint,footpoint;
306                                 float rotationpoint;
307                                 int whichtri;
308
309                                 for(j=0;j<numplayers;j++){
310                                         if(!spritehit&&player[j].dead&&sprites[i]->alivetime>.1){
311                                                 where=sprites[i]->oldposition;
312                                                 where-=player[j].coords;
313                                                 if(!player[j].skeleton.free)where=DoRotation(where,0,-player[j].yaw,0);
314                                                 startpoint=where;
315                                                 where=sprites[i]->position;
316                                                 where-=player[j].coords;
317                                                 if(!player[j].skeleton.free)where=DoRotation(where,0,-player[j].yaw,0);
318                                                 endpoint=where;
319
320                                                 movepoint=0;
321                                                 rotationpoint=0;
322                                                 whichtri=player[j].skeleton.drawmodel.LineCheck(&startpoint,&endpoint, &footpoint, &movepoint, &rotationpoint);
323                                                 if(whichtri!=-1){
324                                                         spritehit=1;
325                                                         player[j].DoBloodBigWhere(0,160,sprites[i]->oldposition);
326                                                         DeleteSprite(i);
327                                                 }
328                                         }
329                                 }
330
331                                 whichpatchx=sprites[i]->position.x/(terrain.size/subdivision*terrain.scale);
332                                 whichpatchz=sprites[i]->position.z/(terrain.size/subdivision*terrain.scale);
333                                 if(whichpatchx>0&&whichpatchz>0&&whichpatchx<subdivision&&whichpatchz<subdivision)
334                                         if(terrain.patchobjectnum[whichpatchx][whichpatchz]){
335                                                 if(!spritehit)
336                                                         for(j=0;j<terrain.patchobjectnum[whichpatchx][whichpatchz];j++){
337                                                                 k=terrain.patchobjects[whichpatchx][whichpatchz][j];
338                                                                 start=sprites[i]->oldposition;
339                                                                 end=sprites[i]->position;
340                                                                 if(!spritehit)
341                                                                         if(objects.model[k].LineCheck(&start,&end,&colpoint,&objects.position[k],&objects.yaw[k])!=-1){
342                                                                                 if(detail==2||(detail==1&&abs(Random()%4)==0)||(detail==0&&abs(Random()%8)==0))objects.model[k].MakeDecal(blooddecalfast,DoRotation(colpoint-objects.position[k],0,-objects.yaw[k],0),sprites[i]->size*1.6/*+abs((float)(Random()%100))/2400*/,.5,Random()%360);
343                                                                                 DeleteSprite(i);
344                                                                                 spritehit=1;
345                                                                         }       
346                                                         }
347                                         }
348                                         if(!spritehit)
349                                                 if(sprites[i]->position.y<terrain.getHeight(sprites[i]->position.x,sprites[i]->position.z)){
350                                                         terrain.MakeDecal(blooddecalfast,sprites[i]->position,sprites[i]->size*1.6/*+abs((float)(Random()%100))/2400*/,.6,Random()%360);
351                                                         DeleteSprite(i);
352                                                 }
353                         }
354                 }
355                 if(sprites[i]->type==splintersprite){
356                         sprites[i]->rotation+=sprites[i]->rotatespeed*multiplier;
357                         sprites[i]->opacity-=multiplier/2;
358                         if(sprites[i]->special==0||sprites[i]->special==2||sprites[i]->special==3)sprites[i]->velocity.y+=gravity*multiplier;
359                         if(sprites[i]->special==1)sprites[i]->velocity.y+=gravity*multiplier*.5;
360                 }
361                 if(sprites[i]->type==flamesprite||sprites[i]->type==weaponflamesprite||sprites[i]->type==weaponshinesprite||sprites[i]->type==bloodflamesprite){
362                         sprites[i]->rotation+=multiplier*sprites[i]->rotatespeed;
363                         sprites[i]->opacity-=multiplier*5/4;
364                         if(sprites[i]->type!=weaponshinesprite&&sprites[i]->type!=bloodflamesprite)
365                                 if(sprites[i]->opacity<.5&&sprites[i]->opacity+multiplier*5/4>=.5&&(abs(Random()%4)==0||(sprites[i]->initialsize>2&&Random()%2==0)))
366                                         MakeSprite(smoketype, sprites[i]->position,sprites[i]->velocity, .9,.9,.6, sprites[i]->size*1.2, .4);
367                         if(sprites[i]->alivetime>.14&&(sprites[i]->type==flamesprite)){
368                                 sprites[i]->velocity=0;
369                                 sprites[i]->velocity.y=1.5;
370                         }
371                 }
372                 if(sprites[i]->type==smoketype){
373                         sprites[i]->opacity-=multiplier/3/sprites[i]->initialsize;
374                         sprites[i]->color[0]-=multiplier;
375                         sprites[i]->color[1]-=multiplier;
376                         sprites[i]->color[2]-=multiplier;
377                         if(sprites[i]->color[0]<.6)sprites[i]->color[0]=.6;
378                         if(sprites[i]->color[1]<.6)sprites[i]->color[1]=.6;
379                         if(sprites[i]->color[2]<.6)sprites[i]->color[2]=.6;
380                         sprites[i]->size+=multiplier;
381                         sprites[i]->velocity=0;
382                         sprites[i]->velocity.y=1.5;
383                         sprites[i]->rotation+=multiplier*sprites[i]->rotatespeed/5;
384                 }
385                 if(sprites[i]->opacity<=0||sprites[i]->size<=0)DeleteSprite(i);
386         }
387         if(check)
388                 for(i=sprites.size()-1;i>=0;i--){
389                         sprites[i]->oldposition=sprites[i]->position;
390                 }
391                 glAlphaFunc(GL_GREATER, 0.0001);
392                 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
393 }
394
395 void Sprite::DeleteSprite(int i)
396 {
397         sprites.erase(sprites.begin()+i);
398 }
399
400 void Sprite::MakeSprite(int atype, XYZ where, XYZ avelocity, float red, float green, float blue, float asize, float aopacity){
401         if(sprites.size()<max_sprites-1){
402                 sprites.push_back(new Sprite());
403                 if((atype!=bloodsprite&&atype!=bloodflamesprite)||bloodtoggle){
404                         sprites.back()->special=0;
405                         sprites.back()->type=atype;
406                         sprites.back()->position=where;
407                         sprites.back()->oldposition=where;
408                         sprites.back()->velocity=avelocity;
409                         sprites.back()->alivetime=0;
410                         sprites.back()->opacity=aopacity;
411                         sprites.back()->size=asize;
412                         sprites.back()->initialsize=asize;
413                         sprites.back()->color[0]=red;
414                         sprites.back()->color[1]=green;
415                         sprites.back()->color[2]=blue;
416                         sprites.back()->rotatespeed=abs(Random()%720)-360;
417                         sprites.back()->speed=float(abs(Random()%100))/200+1.5;
418                 }               
419         }
420 }
421
422 Sprite::Sprite()
423 {
424         oldposition = 0;
425         position = 0;
426         velocity = 0;
427         size = 0;
428         initialsize = 0;
429         type = 0;
430         special = 0;
431         memset(color,0,sizeof(color));
432         opacity = 0;
433         rotation = 0;
434         alivetime = 0;
435         speed = 0;
436         rotatespeed = 0;        
437 }
438
439 void Sprite::clearTextures()
440 {
441         toothtexture.destroy();
442         cloudtexture.destroy();
443         cloudimpacttexture.destroy();
444         bloodtexture.destroy();
445         flametexture.destroy();
446         bloodflametexture.destroy();
447         smoketexture.destroy();
448         snowflaketexture.destroy();
449         shinetexture.destroy();
450         splintertexture.destroy();
451         leaftexture.destroy();
452 }
453