1 /**
2  * @file explosions.c
3  * @brief Handle explosions and explosion fragments
4  * @date 2014-09-18
5  * @author Jean-Michel Martin de Santero
6  * @author Bruno Ethvignot
7  */
8 /*
9  * copyright (c) 1998-2015 TLK Games all rights reserved
10  * $Id: explosions.c,v 1.28 2012/06/03 17:06:15 gurumeditation Exp $
11  *
12  * Powermanga is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * Powermanga is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25  * MA  02110-1301, USA.
26  */
27 #include "config.h"
28 #include "powermanga.h"
29 #include "tools.h"
30 #include "images.h"
31 #include "display.h"
32 #include "electrical_shock.h"
33 #include "log_recorder.h"
34 #include "enemies.h"
35 #include "explosions.h"
36 #include "shots.h"
37 #include "gfx_wrapper.h"
38 #include "sdl_mixer.h"
39 #include "spaceship.h"
40 #include "starfield.h"
41 
42 /** Maximum of enemies active at any time */
43 #define MAX_OF_EXPLOSIONS 200
44 #define EXPLOSIONS_NUMOF_TYPES 3
45 #define EXPLOSIONS_NUMOF_IMAGES 32
46 #define FRAGMENTS_NUMOF_TYPES 5
47 #define FRAGMENTS_NUMOF_IMAGES 32
48 
49 typedef struct explosion_struct
50 {
51   /** Current image index */
52   Sint16 current_image;
53   /** Value of delay between two images */
54   Sint16 anim_speed;
55   /** Counter of delay between two images */
56   Sint16 anim_count;
57   Sint16 img_angle;
58   /** Structures of the explosions images */
59   image *img[EXPLOSIONS_NUMOF_IMAGES];
60   /**  X-coordinate */
61   float xcoord;
62   /** Y-coordinate */
63   float ycoord;
64   /** Speed of the displacement */
65   float speed;
66   struct explosion_struct *previous;
67   struct explosion_struct *next;
68   bool is_enabled;
69   /** Delay before begin explosion animation */
70   Sint32 countdown;
71 } explosion_struct;
72 
73 static image eclat[FRAGMENTS_NUMOF_TYPES][FRAGMENTS_NUMOF_IMAGES];
74 static image explo[EXPLOSIONS_NUMOF_TYPES][EXPLOSIONS_NUMOF_IMAGES];
75 static explosion_struct *explosions = NULL;
76 static explosion_struct *explosion_first = NULL;
77 static explosion_struct *explosion_last = NULL;
78 static Sint32 num_of_explosions = 0;
79 static explosion_struct *explosion_get (void);
80 static void explosion_del (explosion_struct *);
81 
82 /**
83  * Allocate buffers and initialize structure of the explosions
84  * @return TRUE if it completed successfully or FALSE otherwise
85  */
86 bool
explosions_once_init(void)87 explosions_once_init (void)
88 {
89   Uint32 i;
90   explosion_struct *blast;
91   explosions_free ();
92 
93   /* extract explosions sprites images (61,750 bytes) */
94   if (!image_load
95       ("graphics/sprites/explosions.spr", &explo[0][0],
96        EXPLOSIONS_NUMOF_TYPES, EXPLOSIONS_NUMOF_IMAGES))
97     {
98       return FALSE;
99     }
100   /* extract  explosion fragments sprites images (34,089 bytes) */
101   if (!image_load
102       ("graphics/sprites/explosion_fragments.spr", &eclat[0][0],
103        FRAGMENTS_NUMOF_TYPES, FRAGMENTS_NUMOF_IMAGES))
104     {
105       return FALSE;
106     }
107 
108   /* allocate explosions data structure */
109   if (explosions == NULL)
110     {
111       explosions =
112         (explosion_struct *) memory_allocation (MAX_OF_EXPLOSIONS *
113                                                 sizeof (explosion_struct));
114       if (explosions == NULL)
115         {
116           LOG_ERR ("not enough memory to allocate 'explosions'");
117           return FALSE;
118         }
119     }
120   for (i = 0; i < MAX_OF_EXPLOSIONS; i++)
121     {
122       blast = &explosions[i];
123       blast->is_enabled = FALSE;
124     }
125   return TRUE;
126 }
127 
128 /**
129  * Convert explosions from data image to PNG file
130  * @return TRUE if successful
131  */
132 #ifdef PNG_EXPORT_ENABLE
133 bool
explosions_extract(void)134 explosions_extract (void)
135 {
136   Uint32 type, frame;
137   const char *model = EXPORT_DIR "/explosions/explosion/explosion-%01d.png";
138   char *filename = memory_allocation (strlen (model) + 1);
139   if (filename == NULL)
140     {
141       LOG_ERR ("not enough memory to allocate %i bytes\n",
142                (Uint32) (strlen (model) + 1));
143       return FALSE;
144     }
145   if (!create_dir (EXPORT_DIR "/explosions"))
146     {
147       free_memory (filename);
148       return FALSE;
149     }
150   for (type = 0; type < EXPLOSIONS_NUMOF_TYPES; type++)
151     {
152       sprintf (filename, EXPORT_DIR "/explosions/explosion-%01d", type + 1);
153       if (!create_dir (filename))
154         {
155           free_memory (filename);
156           return FALSE;
157         }
158       for (frame = 0; frame < EXPLOSIONS_NUMOF_IMAGES; frame++)
159         {
160           sprintf (filename,
161                    EXPORT_DIR "/explosions/explosion-%01d/explosion-%01d.png",
162                    type + 1, frame);
163           if (!image_to_png (&explo[type][frame], filename))
164             {
165               free_memory (filename);
166               return FALSE;
167             }
168         }
169     }
170   for (type = 0; type < FRAGMENTS_NUMOF_TYPES; type++)
171     {
172       sprintf (filename, EXPORT_DIR "/explosions/fragment-%01d", type + 1);
173       if (!create_dir (filename))
174         {
175           free_memory (filename);
176           return FALSE;
177         }
178       for (frame = 0; frame < FRAGMENTS_NUMOF_IMAGES; frame++)
179         {
180           sprintf (filename,
181                    EXPORT_DIR "/explosions/fragment-%01d/fragment-%01d.png",
182                    type + 1, frame);
183           if (!image_to_png (&eclat[type][frame], filename))
184             {
185               free_memory (filename);
186               return FALSE;
187             }
188         }
189     }
190   free_memory (filename);
191   return TRUE;
192 }
193 #endif
194 
195 /**
196  * Release memory used for the explosions
197  */
198 void
explosions_free(void)199 explosions_free (void)
200 {
201   images_free (&explo[0][0], EXPLOSIONS_NUMOF_TYPES, EXPLOSIONS_NUMOF_IMAGES,
202                EXPLOSIONS_NUMOF_IMAGES);
203   images_free (&eclat[0][0], FRAGMENTS_NUMOF_TYPES, FRAGMENTS_NUMOF_IMAGES,
204                FRAGMENTS_NUMOF_IMAGES);
205   if (explosions != NULL)
206     {
207       free_memory ((char *) explosions);
208       explosions = NULL;
209     }
210 }
211 
212 /**
213  * Handle big, medium, little and special explosions
214  */
215 void
explosions_handle()216 explosions_handle ()
217 {
218   Sint32 i;
219   explosion_struct *blast;
220   blast = explosion_first;
221   if (blast == NULL)
222     {
223       return;
224     }
225   for (i = 0; i < num_of_explosions; i++, blast = blast->next)
226     {
227 #ifdef UNDER_DEVELOPMENT
228       if (blast == NULL && i < (num_of_explosions - 1))
229         {
230           LOG_ERR ("blast->next is null %i/%i", i, num_of_explosions);
231           break;
232         }
233 #endif
234 
235       /* change x and y coordinates */
236       blast->xcoord += depix[(Sint16) blast->speed][blast->img_angle];
237       blast->ycoord += depiy[(Sint16) blast->speed][blast->img_angle];
238 
239       /* delay before begin animation */
240       if (blast->countdown > 0)
241         {
242           blast->countdown--;
243         }
244 
245       /* play sprite animation */
246       else
247         {
248           /* inc. counter of delay between two images */
249           blast->anim_count++;
250           if (blast->anim_count >= blast->anim_speed)
251             {
252               blast->anim_count = 0;
253               /* flip to the next image */
254               blast->current_image++;
255             }
256 
257           /* last image has been reached? */
258           if (
259                /* last image of explosion has been reached? */
260                (blast->anim_speed < 5
261                 && blast->current_image >= EXPLOSIONS_NUMOF_IMAGES) ||
262                /* last image of star has been reached? */
263                (blast->anim_speed > 3
264                 && blast->current_image >= STAR_NUMOF_IMAGES) ||
265                /* explosion move to the bottom out of the screen? */
266                (((Sint16) blast->ycoord +
267                  blast->img[blast->current_image]->h) >=
268                 (offscreen_height - 1)) ||
269                /* explosion move to the right out of the screen? */
270                (((Sint16) blast->xcoord +
271                  blast->img[blast->current_image]->w) >=
272                 (offscreen_width - 1)) ||
273                (((Sint16) blast->xcoord +
274                  blast->img[blast->current_image]->w - 1) < offscreen_startx)
275                ||
276                (((Sint16) blast->ycoord +
277                  blast->img[blast->current_image]->h - 1) < offscreen_starty))
278             {
279               /* remove a explosion or star element from list */
280               explosion_del (blast);
281             }
282           else
283             {
284               /* draw explosion or star sprite */
285               draw_sprite (blast->img[blast->current_image],
286                            (Uint32) blast->xcoord, (Uint32) blast->ycoord);
287             }
288         }
289     }
290 }
291 
292 /**
293  * Add a new explosion
294  * @param coordx X-coordinate
295  * @param coordy Y-coordinate
296  * @param speed Movement speed
297  * @param type Type 0=32*32 / 1=64*14 / 2=16*16 / 3=player's spaceship star
298  * @param delay Delay before begin explosion animation
299  */
300 void
explosion_add(float coordx,float coordy,float speed,Sint32 type,Sint32 delay)301 explosion_add (float coordx, float coordy, float speed, Sint32 type,
302                Sint32 delay)
303 {
304   Sint32 k;
305   explosion_struct *blast;
306   if (type < 0 || type > 3)
307     {
308       return;
309     }
310   /* get a new explosion element */
311   blast = explosion_get ();
312   if (blast == NULL)
313     {
314       return;
315     }
316   /* set current image */
317   blast->current_image = 0;
318   /* clear counter of delay between two images */
319   blast->anim_count = 0;
320   /* set speed of the displacement */
321   blast->speed = speed;
322   blast->img_angle = 8;
323   /* delay before begin explosion animation */
324   blast->countdown = delay;
325   switch (type)
326     {
327       /*
328        * medium explosion of 32*32 pixels size
329        */
330     case EXPLOSION_MEDIUM:
331       blast->anim_speed = 1;
332       /* set addresses of the images buffer */
333       for (k = 0; k < EXPLOSIONS_NUMOF_IMAGES; k++)
334         {
335           blast->img[k] = (image *) & explo[1][k];
336         }
337       /* set x and y coordinates */
338       blast->xcoord = coordx - 8;
339       blast->ycoord = coordy - 8;
340 #ifdef USE_SDLMIXER
341       sound_play (SOUND_MEDIUM_EXPLOSION_1 + (global_counter & 3));
342 #endif
343       break;
344 
345       /*
346        * big explosion of 64*64 pixels size
347        */
348     case EXPLOSION_BIG:
349       blast->anim_speed = 1;
350       for (k = 0; k < EXPLOSIONS_NUMOF_IMAGES; k++)
351         {
352           blast->img[k] = (image *) & explo[2][k];
353         }
354       /* set x and y coordinates */
355       blast->xcoord = coordx - 16;
356       blast->ycoord = coordy - 16;
357 #ifdef USE_SDLMIXER
358       sound_play (SOUND_BIG_EXPLOSION_1 + (global_counter & 3));
359 #endif
360       break;
361 
362       /*
363        * small explosion of 16*16 pixels size
364        */
365     case EXPLOSION_SMALL:
366       blast->anim_speed = 1;
367       for (k = 0; k < EXPLOSIONS_NUMOF_IMAGES; k++)
368         {
369           blast->img[k] = (image *) & explo[0][k];
370         }
371       /* set x and y coordinates */
372       blast->xcoord = coordx - 4;
373       blast->ycoord = coordy - 4;
374 #ifdef USE_SDLMIXER
375       sound_play (SOUND_SMALL_EXPLOSION_1 + (global_counter & 3));
376 #endif
377       break;
378 
379       /*
380        * star on player's spaceship
381        */
382     case 3:
383       /* set value of delay between two images */
384       blast->anim_speed = 6;
385       for (k = 0; k < STAR_NUMOF_IMAGES; k++)
386         {
387           blast->img[k] = (image *) & star_field[STAR_SPACESHIP][k];
388         }
389       /* set x and y coordinates */
390       blast->xcoord = coordx;
391       blast->ycoord = coordy;
392       break;
393     }
394 }
395 
396 /**
397  * Add a new explosion for the guardian only
398  * @param coordx x coordinate
399  * @param coordy y coordinate
400  */
401 void
explosion_guardian_add(float coordx,float coordy)402 explosion_guardian_add (float coordx, float coordy)
403 {
404   Sint32 k;
405   explosion_struct *blast;
406   blast = explosion_get ();
407   if (blast == NULL)
408     {
409       return;
410     }
411   /* set first image */
412   blast->current_image = 0;
413   /* value of delay between two images */
414   blast->anim_speed = 1;
415   /* counter of delay between two images */
416   blast->anim_count = 0;
417   for (k = 0; k < EXPLOSIONS_NUMOF_IMAGES; k++)
418     {
419       blast->img[k] = (image *) & explo[0][k];
420     }
421   /* set x and y coordinates */
422   blast->xcoord = coordx - 4;
423   blast->ycoord = coordy - 4;
424   /* set speed of the displacement */
425   blast->speed = -.5;
426   blast->img_angle = 8;
427   /* delay before begin explosion animation */
428   blast->countdown = 0;
429 #ifdef USE_SDLMIXER
430   if (!(rand () % 8))
431     {
432       sound_play (SOUND_SMALL_EXPLOSION_1 + (global_counter & 3));
433     }
434 #endif
435 }
436 
437 /**
438  * Add one or more explosion fragments
439  * @param coordx X-coordinate
440  * @param coordy Y-coordinate
441  * @param speed Movement speed
442  * @param numof Number of the explosion fragments
443  * @param delay Delay before begin explosion animation
444  * @param anim_speed Time delay between two images
445  */
446 void
explosions_fragments_add(float coordx,float coordy,float speed,Sint32 numof,Sint32 delay,Sint16 anim_speed)447 explosions_fragments_add (float coordx, float coordy, float speed,
448                           Sint32 numof, Sint32 delay, Sint16 anim_speed)
449 {
450   Sint32 i, j, num_eclat;
451   explosion_struct *blast;
452   for (i = 0; i < numof; i++)
453     {
454       blast = explosion_get ();
455       if (blast == NULL)
456         {
457           return;
458         }
459       /* set first image */
460       blast->current_image = 0;
461       /* value of delay between two images */
462       blast->anim_speed = anim_speed;
463       /* counter of delay between two images */
464       blast->anim_count = 0;
465       /* select a explosion fragment image at random */
466       num_eclat = rand () % FRAGMENTS_NUMOF_TYPES;
467       for (j = 0; j < FRAGMENTS_NUMOF_IMAGES; j++)
468         {
469           blast->img[j] = (image *) & eclat[num_eclat][j];
470         }
471       /* set x and y coordinates */
472       blast->xcoord = coordx;
473       blast->ycoord = coordy;
474       /* set speed of the displacement */
475       blast->speed = speed;
476       blast->img_angle = (Sint16) (rand () % 32);
477       /* delay before begin explosion animation */
478       blast->countdown = delay;
479     }
480 }
481 
482 /**
483  * Check validty of explosions chained list
484  */
485 #ifdef UNDER_DEVELOPMENT
486 static void
explosion_check_chained_list(void)487 explosion_check_chained_list (void)
488 {
489   Uint32 i;
490   explosion_struct *blast;
491   Sint32 count = 0;
492   for (i = 0; i < MAX_OF_EXPLOSIONS; i++)
493     {
494       blast = &explosions[i];
495       if (blast->is_enabled)
496         {
497           count++;
498         }
499     }
500   if (count != num_of_explosions)
501     {
502       LOG_ERR ("Counting of the enabled elements failed!"
503                "count=%i, num_of_explosions=%i", count, num_of_explosions);
504     }
505   count = 0;
506   blast = explosion_first;
507   do
508     {
509       count++;
510       blast = blast->next;
511     }
512   while (blast != NULL && count <= (MAX_OF_EXPLOSIONS + 1));
513   if (count != num_of_explosions)
514     {
515       LOG_ERR ("Counting of the next elements failed!"
516                "count=%i, num_of_explosions=%i", count, num_of_explosions);
517     }
518   count = 0;
519   blast = explosion_last;
520   do
521     {
522       count++;
523       blast = blast->previous;
524     }
525   while (blast != NULL && count <= (MAX_OF_EXPLOSIONS + 1));
526   if (count != num_of_explosions)
527     {
528       LOG_ERR ("Counting of the previous elements failed!"
529                "count=%i, num_of_explosions=%i", count, num_of_explosions);
530     }
531 }
532 #endif
533 
534 /**
535  * Return a free explosion element
536  * @return Pointer to a explosion structure
537  */
538 static explosion_struct *
explosion_get(void)539 explosion_get (void)
540 {
541   Uint32 i;
542   explosion_struct *blast;
543   for (i = 0; i < MAX_OF_EXPLOSIONS; i++)
544     {
545       blast = &explosions[i];
546       if (blast->is_enabled)
547         {
548           continue;
549         }
550       blast->is_enabled = TRUE;
551       blast->next = NULL;
552       if (num_of_explosions == 0)
553         {
554           explosion_first = blast;
555           explosion_last = blast;
556           explosion_last->previous = NULL;
557         }
558       else
559         {
560           explosion_last->next = blast;
561           blast->previous = explosion_last;
562           explosion_last = blast;
563         }
564       num_of_explosions++;
565 #ifdef UNDER_DEVELOPMENT
566       explosion_check_chained_list ();
567 #endif
568       return blast;
569     }
570 #ifdef UNDER_DEVELOPMENT
571   LOG_ERR ("no more element explosion is available");
572 #endif
573   return NULL;
574 }
575 
576 /**
577  * Remove a explosion element from list
578  * @param blast Pointer to a explosion structure
579  */
580 void
explosion_del(explosion_struct * blast)581 explosion_del (explosion_struct * blast)
582 {
583   blast->is_enabled = FALSE;
584   num_of_explosions--;
585   if (explosion_first == blast)
586     {
587       explosion_first = blast->next;
588     }
589   if (explosion_last == blast)
590     {
591       explosion_last = blast->previous;
592     }
593   if (blast->previous != NULL)
594     {
595       blast->previous->next = blast->next;
596     }
597   if (blast->next != NULL)
598     {
599       blast->next->previous = blast->previous;
600     }
601 }
602 
603 /**
604  * Add a serie of explosions
605  * @param Pointer to enemy structure or NULL if player's spaceship
606  */
607 void
explosions_add_serie(enemy * foe)608 explosions_add_serie (enemy * foe)
609 {
610   Sint32 type_of_vessel;
611   Uint32 coordx, coordy, width, height;
612   Sint32 height_big, height_normal, height_small, width_big, width_normal,
613     width_small;
614   spaceship_struct *ship = spaceship_get ();
615 
616   /*
617    * enemy vessel
618    */
619   if (foe != NULL)
620     {
621       type_of_vessel = 0;
622       if (foe->spr.img[foe->spr.current_image]->w > 32)
623         {
624           type_of_vessel += 2;
625         }
626       if (foe->spr.img[foe->spr.current_image]->h > 32)
627         {
628           type_of_vessel += 4;
629         }
630       coordx = (Uint32) foe->spr.xcoord;
631       coordy = (Uint32) foe->spr.ycoord;
632       width = foe->spr.img[foe->spr.current_image]->w;
633       height = foe->spr.img[foe->spr.current_image]->h;
634     }
635   else
636     {
637       type_of_vessel = -1;
638       coordx = (Uint32) ship->spr.xcoord;
639       coordy = (Uint32) ship->spr.ycoord;
640       width = ship->spr.img[ship->spr.current_image]->w;
641       height = ship->spr.img[ship->spr.current_image]->h;
642     }
643 
644   height_big = height - 32;
645   if (height_big < 1)
646     {
647       height_big = 1;
648     }
649 
650   height_normal = height - 16;
651   if (height_normal < 1)
652     {
653       height_normal = 1;
654     }
655 
656   height_small = height - 8;
657   if (height_small < 1)
658     {
659       height_small = 1;
660     }
661 
662   width_big = width - 32;
663   if (width_big < 1)
664     {
665       width_big = 1;
666     }
667 
668   width_normal = width - 16;
669   if (width_normal < 1)
670     {
671       width_normal = 1;
672     }
673 
674   width_small = width - 8;
675   if (width_small < 1)
676     {
677       width_small = 1;
678     }
679 
680   switch (type_of_vessel)
681     {
682       /*
683        * player's spaceship
684        */
685     case -1:
686       explosion_add ((float) coordx, (float) coordy, 0.3f, EXPLOSION_BIG, 0);
687       explosion_add ((float) (coordx + (rand () % width_normal)),
688                      (float) (coordy + (rand () % height_normal)), 0.3f,
689                      EXPLOSION_MEDIUM, 20);
690       explosion_add ((float) (coordx + (rand () % width_normal)),
691                      (float) (coordy + (rand () % height_normal)),
692                      0.3f, EXPLOSION_MEDIUM, 30);
693       explosion_add ((float) (coordx + (rand () % width_normal)),
694                      (float) (coordy + (rand () % height_normal)),
695                      0.3f, EXPLOSION_MEDIUM, 40);
696       explosion_add ((float) (coordx + (rand () % width_normal)),
697                      (float) (coordy + (rand () % height_normal)),
698                      0.3f, EXPLOSION_MEDIUM, 50);
699       explosion_add ((float) (coordx + (rand () % width_small)),
700                      (float) (coordy + (rand () % height_small)),
701                      0.3f, EXPLOSION_SMALL, 30);
702       explosion_add ((float) (coordx + (rand () % width_small)),
703                      (float) (coordy + (rand () % height_small)),
704                      0.3f, EXPLOSION_SMALL, 40);
705       explosion_add ((float) (coordx + (rand () % width_small)),
706                      (float) (coordy + (rand () % height_small)),
707                      0.3f, EXPLOSION_SMALL, 50);
708       explosion_add ((float) (coordx + (rand () % width_small)),
709                      (float) (coordy + (rand () % height_small)),
710                      0.3f, EXPLOSION_SMALL, 60);
711       explosion_add ((float) (coordx + (rand () % width_small)),
712                      (float) (coordy + (rand () % height_small)),
713                      0.3f, EXPLOSION_SMALL, 70);
714       explosion_add ((float) (coordx + (rand () % width_small)),
715                      (float) (coordy + (rand () % height_small)),
716                      0.3f, EXPLOSION_SMALL, 80);
717       break;
718       /* enemy is lower than 32 width and height pixels */
719     case 0:
720       explosion_add ((float) coordx, (float) coordy, 0.3f, EXPLOSION_BIG, 0);
721       explosion_add ((float) (coordx + (rand () % width_normal)),
722                      (float) (coordy + (rand () % height_normal)),
723                      0.3f, EXPLOSION_MEDIUM, 10);
724       explosion_add ((float) (coordx + (rand () % width_normal)),
725                      (float) (coordy + (rand () % height_normal)),
726                      0.3f, EXPLOSION_MEDIUM, 20);
727       explosion_add ((float) (coordx + (rand () % width_small)),
728                      (float) (coordy + (rand () % height_small)),
729                      0.3f, EXPLOSION_SMALL, 30);
730       explosion_add ((float) (coordx + (rand () % width_small)),
731                      (float) (coordy + (rand () % height_small)),
732                      0.3f, EXPLOSION_SMALL, 40);
733       break;
734       /* enemy is higher than 32 width pixels */
735     case 2:
736       explosion_add ((float) (coordx + (rand () % width_big)),
737                      (float) coordy, 0.3f, EXPLOSION_BIG, 0);
738       explosion_add ((float) coordx + (rand () % width_big),
739                      (float) coordy, 0.3f, EXPLOSION_BIG, 10);
740       explosion_add ((float) (coordx + (rand () % width_normal)),
741                      (float) (coordy + (rand () % height_normal)),
742                      0.3f, EXPLOSION_MEDIUM, 20);
743       explosion_add ((float) (coordx + (rand () % width_normal)),
744                      (float) (coordy + (rand () % height_normal)),
745                      0.3f, EXPLOSION_MEDIUM, 30);
746       explosion_add ((float) (coordx + (rand () % width_small)),
747                      (float) (coordy + (rand () % height_small)),
748                      0.3f, EXPLOSION_SMALL, 40);
749       explosion_add ((float) (coordx + (rand () % width_small)),
750                      (float) (coordy + (rand () % height_small)),
751                      0.3f, EXPLOSION_SMALL, 50);
752       break;
753       /* enemy is higher than 32 height pixels */
754     case 4:
755       explosion_add ((float) coordx,
756                      (float) (coordy + (rand () % height_big)),
757                      0.3f, EXPLOSION_BIG, 0);
758       explosion_add ((float) coordx,
759                      (float) coordy + (rand () % height_big),
760                      0.3f, EXPLOSION_BIG, 10);
761       explosion_add ((float) (coordx + (rand () % width_normal)),
762                      (float) (coordy + (rand () % height_normal)),
763                      0.3f, EXPLOSION_MEDIUM, 20);
764       explosion_add ((float) (coordx + (rand () % width_normal)),
765                      (float) (coordy + (rand () % height_normal)),
766                      0.3f, EXPLOSION_MEDIUM, 30);
767       explosion_add ((float) (coordx + (rand () % width_small)),
768                      (float) (coordy + (rand () % height_small)),
769                      0.3f, EXPLOSION_SMALL, 40);
770       explosion_add ((float) (coordx + (rand () % width_small)),
771                      (float) (coordy + (rand () % height_small)),
772                      0.3f, EXPLOSION_SMALL, 50);
773       break;
774       /* enemy is higher than 32 width and height pixels */
775     case 6:
776       explosion_add ((float) (coordx + (rand () % width_big)),
777                      (float) (coordy + (rand () % height_big)),
778                      0.3f, EXPLOSION_BIG, 0);
779       explosion_add ((float) (coordx + (rand () % width_big)),
780                      (float) (coordy + (rand () % height_big)),
781                      0.3f, EXPLOSION_BIG, 10);
782       explosion_add ((float) (coordx + (rand () % width_normal)),
783                      (float) (coordy + (rand () % height_normal)),
784                      0.3f, EXPLOSION_MEDIUM, 20);
785       explosion_add ((float) (coordx + (rand () % width_normal)),
786                      (float) (coordy + (rand () % height_normal)),
787                      0.3f, EXPLOSION_MEDIUM, 30);
788       explosion_add ((float) (coordx + (rand () % width_small)),
789                      (float) (coordy + (rand () % height_small)),
790                      0.3f, EXPLOSION_SMALL, 40);
791       explosion_add ((float) (coordx + (rand () % width_small)),
792                      (float) (coordy + (rand () % height_small)),
793                      0.3f, EXPLOSION_SMALL, 50);
794       break;
795     }
796 }
797