1 /*------------------------------------------------------------------
2   effects.c:
3 
4     XINVADERS 3D - 3d Shoot'em up
5     Copyright (C) 2000 Don Llopis
6 
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11 
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     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 "game.h"
23 
24 /*------------------------------------------------------------------
25  * Stars
26  *
27  *
28 ------------------------------------------------------------------*/
29 
30 enum stars_enum
31 {
32    MAX_STARS = 100
33 };
34 
35 struct STARSSTRUCT
36 {
37    VECTOR4      pos;
38    VECTOR4      thrustz;
39    int          thrust;
40    unsigned int color;
41 } stars[MAX_STARS];
42 
43 VECTOR4 star_start     = { 0.0f, 0.0f, -2000.0f, 1.0f };
44 VECTOR4 star_thrust[4] = {{ 0.0f, 0.0f, 50.0f, 1.0f },
45                          { 0.0f, 0.0f, 25.0f, 1.0f },
46                          { 0.0f, 0.0f, 15.0f, 1.0f },
47                          { 0.0f, 0.0f, 10.0f, 1.0f } };
48 
49 
Stars_init(void)50 void Stars_init ( void )
51 {
52    int i, j, k, l, m;
53    for ( i=0; i<MAX_STARS; i++ )
54    {
55       m = rand () % 4;
56       j = rand () % 800;
57       k = rand () % 800;
58       l = rand () % 1000;
59       Vector_copy ( star_start, stars[i].pos );
60 
61       stars[i].pos[XPOS] = (float)j;
62       stars[i].pos[YPOS] = (float)k;
63 
64       if ( (i % 3) == 0 )
65       {
66          stars[i].pos[XPOS] *= -1.0f;
67          if ( (i%2) == 0 )
68          {
69             stars[i].pos[YPOS] *= -1.0f;
70          }
71       }
72 
73       stars[i].thrust = m;
74       stars[i].color = WHITE - (m*15);
75    }
76 }
77 
Stars_draw(MATRIX4 r)78 void Stars_draw ( MATRIX4 r )
79 {
80    VECTOR4 tmp;
81    int i, j, m, p[2];
82 
83    for ( i=0; i<MAX_STARS; i++ )
84    {
85       j = stars[i].thrust;
86       stars[i].pos[ZPOS] += star_thrust[j][ZPOS] * gv->fadjust;
87 
88       if ( stars[i].pos[ZPOS] > -1.0f )
89       {
90          m = rand() % 4;
91          stars[i].thrust = m;
92          stars[i].color = WHITE - (m*15);
93          stars[i].pos[ZPOS] = -2000.0f;
94       }
95       Matrix_vec_mult ( r, stars[i].pos, tmp );
96       Camera_project_point ( tmp, p );
97       Draw_point ( p[0], p[1], stars[i].color );
98    }
99 }
100 
101 /*------------------------------------------------------------------
102  * Explosions
103  *
104  *
105 ------------------------------------------------------------------*/
106 
107 #define EXPLOSION_ROT 0.23f
108 
109 enum explosions_enum
110 {
111    MAX_EXPLOSIONS        = 10,
112    MAX_PARTICLES         = 4,
113    EXPLOSIONS_LIFE       = 1500, /* 1.5 sec */
114    EXPLOSION_BLEND_TIME  = 375,  /* 0.375 sec */
115    EXPLOSION_COLOR_INC   = 15
116 };
117 
118 struct EXPLOSIONSTRUCT
119 {
120    VECTOR4  pos[MAX_PARTICLES];
121    int  thrust[MAX_PARTICLES];
122    long frame;
123    long blend;
124    int  color;
125    int  active;
126 } explosions[MAX_EXPLOSIONS];
127 
128 static int   ecur;   /* EXPLOSION index */
129 static int   ecount; /* EXPLOSION count */
130 static int   pcur;   /* THURST index */
131 static float erot;   /* EXPLOSIONS rotation */
132 
133 /* shard/particle thrust vectors */
134 VECTOR4 pthrust[8] = { {-2.0f, 0.0f, 0.0f, 1.0f},
135                       {0.0f, -2.0f, 0.0f, 1.0f},
136                       {2.0f, 0.0f, 0.0f, 1.0f},
137                       {0.0f, 2.0f, 0.0f, 1.0f},
138                       {-2.0f, 2.0f, 0.0f, 1.0f},
139                       {2.0f, -2.0f, 0.0f, 1.0f},
140                       {-2.0f, -2.0f, 0.0f, 1.0f},
141                       {2.0f, 2.0f, 0.0f, 1.0f} };
142 
143 
144 VECTOR4 shard[3] = { {-5.0f, 0.0f, 0.0f, 1.0f},
145                     { 0.0f, 5.0f, 0.0f, 1.0f},
146                     { 5.0f, -5.0f, 0.0f, 1.0f}};
147 
148 
Explosions_clear(void)149 void Explosions_clear ( void )
150 {
151    int i, j;
152 
153    ecur = 0;
154    ecount = 0;
155    pcur = 0;
156 
157    erot = 0.0f;
158 
159    for ( i=0; i<MAX_EXPLOSIONS; i++ )
160    {
161       explosions[i].active = FALSE;
162       explosions[i].frame = 0L;
163       for (j=0; j<MAX_PARTICLES; j++ )
164          Vector_init ( explosions[i].pos[j] );
165    }
166 }
167 
Explosions_count(void)168 int Explosions_count ( void )
169 {
170    return ecount;
171 }
172 
Explosions_add(OBJECT * obj)173 void Explosions_add ( OBJECT *obj )
174 {
175    explosions[ecur].active = TRUE;
176    explosions[ecur].frame = 0;
177    explosions[ecur].color = GREEN;
178    explosions[ecur].blend = 0;
179 
180    /* ok there are currently only 4 */
181    Vector_copy ( obj->pos, explosions[ecur].pos[0] );
182    Vector_copy ( obj->pos, explosions[ecur].pos[1] );
183    Vector_copy ( obj->pos, explosions[ecur].pos[2] );
184    Vector_copy ( obj->pos, explosions[ecur].pos[3] );
185 
186    explosions[ecur].thrust[0] = pcur;
187    explosions[ecur].thrust[1] = pcur+1;
188    explosions[ecur].thrust[2] = pcur+2;
189    explosions[ecur].thrust[3] = pcur+3;
190 
191    ecur++;
192    pcur += 4;
193    ecount++;
194 
195    if ( ecur > MAX_EXPLOSIONS-1 )
196       ecur = 0;
197 
198    if ( pcur == 8 )
199       pcur = 0;
200 }
201 
Explosions_draw(MATRIX4 r)202 void Explosions_draw ( MATRIX4 r )
203 {
204    int i, j, k, p0[6];
205    VECTOR4 tmp[3], shard_tmp[3];
206    MATRIX4 tmp_mat, tmp_mat2, erot_mat;
207 
208    erot += EXPLOSION_ROT * gv->fadjust;
209    Matrix_x_rot ( tmp_mat, erot );
210    Matrix_z_rot ( tmp_mat2, erot );
211    Matrix_mult  ( tmp_mat, tmp_mat2, erot_mat );
212    Matrix_vec_multn ( erot_mat, shard, shard_tmp, 3 );
213 
214    for ( i=0; i<MAX_EXPLOSIONS; i++ )
215    {
216       if ( explosions[i].active )
217       {
218          explosions[i].frame += gv->msec;
219          if ( explosions[i].frame > EXPLOSIONS_LIFE )
220          {
221             explosions[i].active = FALSE;
222             ecount--;
223          }
224          explosions[i].blend += gv->msec;
225          if ( explosions[i].blend > EXPLOSION_BLEND_TIME )
226          {
227             explosions[i].blend -= EXPLOSION_BLEND_TIME;
228             explosions[i].color -= EXPLOSION_COLOR_INC;
229          }
230 
231          for ( j=0; j<MAX_PARTICLES; j++ )
232          {
233             k = explosions[i].thrust[j];
234             explosions[i].pos[j][XPOS] += pthrust[k][XPOS] * gv->fadjust;
235             explosions[i].pos[j][YPOS] += pthrust[k][YPOS] * gv->fadjust;
236             explosions[i].pos[j][ZPOS] += pthrust[k][ZPOS] * gv->fadjust;
237 
238             Matrix_vec_mult ( r, explosions[i].pos[j], tmp[0] );
239             Matrix_copy ( r, tmp_mat );
240             Matrix_set_trans ( tmp_mat, tmp[0] );
241 
242             Matrix_vec_multn ( tmp_mat, shard_tmp, tmp, 3 );
243             Camera_project_points ( tmp, p0, 3 );
244 
245             Draw_line ( p0[0], p0[1], p0[2], p0[3], explosions[i].color );
246             Draw_line ( p0[2], p0[3], p0[4], p0[5], explosions[i].color );
247             Draw_line ( p0[4], p0[5], p0[0], p0[1], explosions[i].color );
248          }
249       }
250    }
251 }
252 
253 /*------------------------------------------------------------------
254  * Jump-gate
255  *
256  *
257 ------------------------------------------------------------------*/
258 
259 enum jumpgate_enum
260 {
261    MAX_JUMPGATES   = 4,
262    JUMPGATE_TIME   = 5000,
263    JUMPGATE_ANIM   = 250,
264    JUMPGATE_FRAMES = 3
265 };
266 
267 struct JUMPGATESTRUCT
268 {
269    int  active;
270    long time;
271    long anim;
272    long frame;
273    int  dir;
274    VECTOR4  pos;
275 } jgates[MAX_JUMPGATES];
276 
277 static int jgcur;   /* JUMPGATE index */
278 static int jcount;  /* JUMPGATE counter */
279 
280 static VECTOR4 jgvert[32] =
281 {
282    {-10.0f, 0.0f, 10.0f, 1.0f},
283    {-0.0f, 10.0f, -10.0f, 1.0f},
284    {10.0f, 0.0f, -10.0f, 1.0f},
285    {0.0f, -10.0f, 10.0f, 1.0f},
286 
287    {-30.0f, 0.0f, 30.0f, 1.0f},
288    {0.0f, 30.0f, -30.0f, 1.0f},
289    {30.0f, 0.0f, -30.0f, 1.0f},
290    {0.0f, -30.0f, 30.0f, 1.0f},
291 
292    {-50.0f, 0.0f, 50.0f, 1.0f},
293    {0.0f, 50.0f, -50.0f, 1.0f},
294    {50.0f, 0.0f, -50.0f, 1.0f},
295    {0.0f, -50.0f, 50.0f, 1.0f},
296 
297    {-70.0f, 0.0f, 70.0f, 1.0f},
298    {0.0f, 70.0f, -70.0f, 1.0f},
299    {70.0f, 0.0f, -70.0f, 1.0f},
300    {0.0f, -70.0f, 70.0f, 1.0f},
301 
302    {-10.0f, 0.0f, -10.0f, 1.0f},
303    {0.0f, 10.0f, 10.0f, 1.0f},
304    {10.0f, 0.0f, 10.0f, 1.0f},
305    {0.0f, -10.0f, -10.0f, 1.0f},
306 
307    {-30.0f, 0.0f, -30.0f, 1.0f},
308    {0.0f, 30.0f, 30.0f, 1.0f},
309    {30.0f, 0.0f, 30.0f, 1.0f},
310    {0.0f, -30.0f, -30.0f, 1.0f},
311 
312    {-50.0f, 0.0f, -50.0f, 1.0f},
313    {0.0f, 50.0f, 50.0f, 1.0f},
314    {50.0f, 0.0f, 50.0f, 1.0f},
315    {0.0f, -50.0f, -50.0f, 1.0f},
316 
317    {-70.0f, 0.0f, -70.0f, 1.0f},
318    {0.0f, 70.0f, 70.0f, 1.0f},
319    {70.0f, 0.0f, 70.0f, 1.0f},
320    {0.0f, -70.0f, -70.0f, 1.0f}
321 };
322 
Jumpgate_init(void)323 void Jumpgate_init ( void )
324 {
325    int i;
326    for ( i=0; i<MAX_JUMPGATES; i++ )
327    {
328       jgates[i].active = FALSE;
329       jgates[i].time   = 0;
330       jgates[i].anim   = 0;
331       jgates[i].frame  = 0;
332       jgates[i].dir    = 0;
333       Vector_init ( jgates[i].pos );
334    }
335    jgcur   = 0;
336    jcount  = 0;
337 }
338 
Jumpgate_open(VECTOR4 pos,int dir)339 void Jumpgate_open ( VECTOR4 pos, int dir )
340 {
341    if ( jcount > MAX_JUMPGATES-1 ) return;
342 
343    jgates[jgcur].active = TRUE;
344    jgates[jgcur].time   = 0;
345    jgates[jgcur].anim   = 0;
346    jgates[jgcur].frame  = 0;
347    jgates[jgcur].dir    = dir * 16;
348    Vector_copy  ( pos, jgates[jgcur].pos );
349 
350    jgcur++;
351    if ( jgcur > MAX_JUMPGATES-1 )
352       jgcur = 0;
353 
354    jcount++;
355 }
356 
Jumpgate_animate(MATRIX4 r)357 void Jumpgate_animate ( MATRIX4 r )
358 {
359    MATRIX4 tmp_mat;
360    VECTOR4 tmp[16];
361    int    i, j, p[32], f0;
362 
363    for ( i=0; i<MAX_JUMPGATES; i++ )
364    {
365 
366       if ( jgates[i].active )
367       {
368          jgates[i].time += gv->msec;
369          jgates[i].anim += gv->msec;
370 
371          if ( jgates[i].anim > JUMPGATE_ANIM )
372          {
373             jgates[i].anim -= JUMPGATE_ANIM;
374             jgates[i].frame += 1;
375             if ( jgates[i].frame > JUMPGATE_FRAMES )
376                jgates[i].frame = 0;
377          }
378 
379          if ( jgates[i].time > JUMPGATE_TIME )
380          {
381             jgates[i].active = FALSE;
382             jcount--;
383          }
384 
385          /* draw jumpgate */
386          Matrix_vec_mult ( r, jgates[i].pos, tmp[0] );
387          Matrix_copy ( r, tmp_mat );
388          Matrix_set_trans ( tmp_mat, tmp[0] );
389 
390          f0 = ( jgates[i].frame + 1 ) * 4;
391          Matrix_vec_multn ( tmp_mat,
392                &jgvert[jgates[i].dir], tmp, f0 );
393          Camera_project_points ( tmp, p, f0 );
394          for ( j=0; j<((f0*2)-4); j+=8 )
395          {
396             Draw_line ( p[0+j], p[1+j], p[2+j], p[3+j], GREEN );
397             Draw_line ( p[2+j], p[3+j], p[4+j], p[5+j], GREEN );
398             Draw_line ( p[4+j], p[5+j], p[6+j], p[7+j], GREEN );
399             Draw_line ( p[6+j], p[7+j], p[0+j], p[1+j], GREEN );
400          }
401       }
402    }
403 }
404 
405 /*------------------------------------------------------------------
406  * One-up!!!
407  *
408  *
409 ------------------------------------------------------------------*/
410 
411 enum oneup_enum
412 {
413    ONEUP_LIFE       = 2000,
414    ONEUP_BLEND_TIME = 200
415 };
416 
417 struct ONEUPSTRUCT
418 {
419    VECTOR4  pos;
420    long frame;
421    long blend;
422    long color;
423    int  active;
424 }one_up;
425 
426 static VECTOR4 one_up_vert[10] =
427 {
428    {-40.0f, 20.0f, 0.0f, 1.0f} ,  /* 1 */
429    {-40.0f, -20.0f, 0.0f, 1.0f },
430    {-20.0f, 20.0f, 0.0f, 1.0f  }, /* U */
431    {-20.0f, -20.0f, 0.0f, 1.0f },
432    { 10.0f, -20.0f, 0.0f, 1.0f },
433    { 10.0f, 20.0f, 0.0f, 1.0f  },
434    { 20.0f, 20.0f, 0.0f, 1.0f  }, /* P */
435    { 20.0f, -20.0f, 0.0f, 1.0f },
436    { 60.0f, 0.0f, 0.0f, 1.0f },
437    { 20.0f, 0.0f, 0.0, 1.0f }
438 };
439 
440 static VECTOR4 oneup_thrust = { 0.0f, 0.0f, 10.0f, 1.0f };
441 
One_up_init(void)442 void One_up_init ( void )
443 {
444    one_up.active = FALSE;
445 }
446 
One_up_add(OBJECT * obj)447 void One_up_add  ( OBJECT *obj )
448 {
449    if ( one_up.active == FALSE )
450    {
451       one_up.active = TRUE;
452       Vector_copy ( obj->pos, one_up.pos );
453       one_up.frame = 0;
454       one_up.blend = 0;
455       one_up.color = WHITE;
456    }
457 }
458 
One_up_draw(MATRIX4 r)459 void One_up_draw ( MATRIX4 r )
460 {
461    int p0[20];
462    VECTOR4 tmp[10];
463    MATRIX4 tmp_mat;
464 
465    if ( one_up.active )
466    {
467       one_up.pos[ZPOS] += oneup_thrust[ZPOS] * gv->fadjust;
468       if ( one_up.pos[ZPOS] > -50.0f )
469          one_up.active = FALSE;
470       one_up.frame += gv->msec;
471       if ( one_up.frame > ONEUP_LIFE )
472       {
473          one_up.active = FALSE;
474       }
475       one_up.blend += gv->msec;
476       if ( one_up.blend > ONEUP_BLEND_TIME )
477       {
478          one_up.blend -= ONEUP_BLEND_TIME;
479          one_up.color -= 3;
480       }
481 
482       /* draw one_up */
483       Matrix_vec_mult ( r, one_up.pos, tmp[0] );
484       Matrix_copy ( r, tmp_mat );
485       Matrix_set_trans ( tmp_mat, tmp[0] );
486 
487       Matrix_vec_multn ( tmp_mat, one_up_vert, tmp, 10 );
488       Camera_project_points ( tmp, p0, 10 );
489 
490       /* draw 1 */
491       Draw_line ( p0[0], p0[1], p0[2], p0[3], one_up.color );
492 
493       /* draw U */
494       Draw_line ( p0[4], p0[5], p0[6], p0[7], one_up.color );
495       Draw_line ( p0[6], p0[7], p0[8], p0[9], one_up.color );
496       Draw_line ( p0[8], p0[9], p0[10], p0[11], one_up.color );
497 
498       /* draw P */
499       Draw_line ( p0[12], p0[13], p0[14], p0[15], one_up.color );
500       Draw_line ( p0[12], p0[13], p0[16], p0[17], one_up.color );
501       Draw_line ( p0[16], p0[17], p0[18], p0[19], one_up.color );
502    }
503 }
504