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