1 /***************************************************************************
2                           shrapnells.c  -  description
3                              -------------------
4     begin                : Sat Sep 8 2001
5     copyright            : (C) 2001 by Michael Speck
6     email                : kulkanie@gmx.net
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include "ltris.h"
19 #include "config.h"
20 #include "list.h"
21 #include "shrapnells.h"
22 
23 extern Config config;
24 extern Sdl sdl;
25 extern SDL_Surface *offscreen;
26 List *shrapnells = 0;
27 
28 /*
29 ====================================================================
30 Local
31 ====================================================================
32 */
33 
34 /*
35 ====================================================================
36 Create a single shrapnell and add to list.
37 ====================================================================
38 */
shrapnell_create(int x,int y,int w,int h,float vx,float vy,float gx,float gy)39 void shrapnell_create( int x, int y, int w, int h, float vx, float vy, float gx, float gy )
40 {
41     Shrapnell *shr = calloc( 1, sizeof( Shrapnell ) );
42     shr->pic = create_surf(w, h, SDL_SWSURFACE);
43     SDL_SetColorKey(shr->pic, 0, 0);
44     DEST(shr->pic, 0, 0, w, h);
45     SOURCE(offscreen, x, y);
46     blit_surf();
47     shr->x = x;
48     shr->y = y;
49     shr->v.x = vx;
50     shr->v.y = vy;
51     shr->g.x = gx;
52     shr->g.y = gy;
53     shr->alpha = 64;
54     list_add( shrapnells, shr);
55 }
56 /*
57 ====================================================================
58 Delete a shrapnell
59 ====================================================================
60 */
shrapnell_delete(void * ptr)61 void shrapnell_delete( void *ptr )
62 {
63     Shrapnell *shr = (Shrapnell*)ptr;
64     SDL_FreeSurface( shr->pic );
65     free( shr );
66 }
67 
68 /*
69 ====================================================================
70 Public
71 ====================================================================
72 */
73 
74 /*
75 ====================================================================
76 Initate or delete shrapnell list
77 ====================================================================
78 */
shrapnells_init()79 void shrapnells_init()
80 {
81     shrapnells = list_create( LIST_AUTO_DELETE, shrapnell_delete );
82 }
shrapnells_delete()83 void shrapnells_delete()
84 {
85     list_delete( shrapnells );
86 }
87 /*
88 ====================================================================
89 Create shrapnells from position in offscreen for one line of blocks.
90 ====================================================================
91 */
shrapnells_create(int x,int y,int w,int h)92 void shrapnells_create( int x, int y, int w, int h )
93 {
94 	int type, i, j;
95 	int shr_w = BOWL_BLOCK_SIZE, shr_h = h;
96 	float vx;
97 
98 	type = rand() % 8;
99 	if (config.anim == 0)
100 		type = 0;
101 
102 	/* create shrapnells */
103 	switch (type) {
104 	case 0:
105 		/* simple sideways animation */
106 		for ( i = 0, j = 1; i < w; i += shr_w, j++ ) {
107 			if (j <= 5)
108 				vx = (j-1) * -0.0667;
109 			else
110 				vx = (10 - j) * 0.0667;
111 			shrapnell_create(x + i, y, shr_w, shr_h, vx, 0, 0, 0);
112 		}
113 		break;
114 	case 1:
115 	case 2:
116 		for ( i = 0, j = 1; i < w; i += shr_w, j++ ) {
117 			if ( type == 1 )
118 				shrapnell_create(x + i, y, shr_w, shr_h, 0, ( 11 - j ) * -0.015, 0, 0.0002 );
119 			else
120 				shrapnell_create(x + i, y, shr_w, shr_h, 0, j * -0.015, 0, 0.0002 );
121 		}
122 		break;
123 	case 3:
124 	case 4:
125 		for ( i = 0, j = 1; i < w / 2; i += shr_w, j++ ) {
126 			if ( type == 3 ) {
127 				shrapnell_create( x + i, y, shr_w, shr_h, 0, j * -0.016, 0, 0.0002 );
128 				shrapnell_create( x + w - i - shr_w, y, shr_w, shr_h, 0, j * -0.016, 0, 0.0002 );
129 			}
130 			else {
131 				shrapnell_create( x + i, y, shr_w, shr_h, 0, ( 6 - j ) * -0.016, 0, 0.0002 );
132 				shrapnell_create( x + w - i - shr_w, y, shr_w, shr_h, 0, ( 6 - j ) * -0.016, 0, 0.0002 );
133 			}
134 		}
135 		break;
136 	case 5:
137 		for ( i = 0, j = 1; i < w / 2; i += shr_w, j++ ) {
138 			shrapnell_create( x + i, y, shr_w, shr_h, ( 6 - j ) * 0.02, 0, 0, 0 );
139 			shrapnell_create( x + w - i - shr_w, y, shr_w, shr_h, ( 6 - j ) * -0.02, 0, 0, 0 );
140 		}
141 		break;
142 	case 6:
143 	case 7:
144 		for ( i = 0, j = 1; i < w; i += shr_w, j++ ) {
145 			if ( type == 6 )
146 				shrapnell_create( x + i, y, shr_w, shr_h, j * -0.02, ( 11 - j ) * -0.01, 0, 0.0002 );
147 			else
148 				shrapnell_create( x + i, y, shr_w, shr_h, ( 11 - j ) * 0.02, ( 11 - j ) * -0.01, 0, 0.0002 );
149 		}
150 		break;
151 	}
152 }
153 /*
154 ====================================================================
155 Remove all shrapnells
156 ====================================================================
157 */
shrapnells_reset()158 void shrapnells_reset()
159 {
160     list_clear( shrapnells );
161 }
162 /*
163 ====================================================================
164 Show, hide all shrapnells.
165 ====================================================================
166 */
shrapnells_hide()167 void shrapnells_hide()
168 {
169     List_Entry  *entry = shrapnells->head.next;
170     Shrapnell   *shr;
171     int         x, y;
172     while ( entry != &shrapnells->tail ) {
173         shr = entry->item;
174         x = (int)shr->x;
175         y = (int)shr->y;
176         DEST(sdl.screen, x, y, shr->pic->w, shr->pic->h);
177         SOURCE(offscreen, x, y);
178         blit_surf();
179         add_refresh_rect(x, y, shr->pic->w, shr->pic->h);
180         entry = entry->next;
181     }
182 }
shrapnells_show()183 void shrapnells_show()
184 {
185     List_Entry  *entry = shrapnells->head.next;
186     Shrapnell   *shr;
187     int         x, y;
188     while ( entry != &shrapnells->tail ) {
189         shr = entry->item;
190         x = (int)shr->x;
191         y = (int)shr->y;
192         DEST(sdl.screen, x, y, shr->pic->w, shr->pic->h);
193         SOURCE(shr->pic, 0, 0);
194         if (shr->alpha == 0)
195             blit_surf();
196         else
197             alpha_blit_surf((int)shr->alpha);
198         add_refresh_rect(x, y, shr->pic->w, shr->pic->h);
199         entry = entry->next;
200     }
201 }
202 /*
203 ====================================================================
204 Update and remove expired shrapnells
205 ====================================================================
206 */
shrapnells_update(int ms)207 void shrapnells_update( int ms )
208 {
209     List_Entry  *entry = shrapnells->head.next;
210     Shrapnell   *shr;
211     while ( entry != &shrapnells->tail ) {
212         shr = entry->item;
213         shr->v.x += shr->g.x * ms;
214         shr->v.y += shr->g.y * ms;
215         shr->x += shr->v.x * ms;
216         shr->y += shr->v.y * ms;
217         if (shr->alpha < 255)
218             shr->alpha += 0.64 * ms;
219         entry = entry->next;
220         if (shr->alpha >= 255 || shr->x + shr->pic->w < 0 || shr->y + shr->pic->h < 0 || shr->x > sdl.screen->w || shr->y > sdl.screen->h)
221             list_delete_entry( shrapnells, entry->prev );
222     }
223 }
224 
225 /*
226 ====================================================================
227 Brick explosion animations.
228 ====================================================================
229 */
230 #define exp_change 0.008
231 #define exp_alpha_change 0.2
232 List *exps;
233 SDL_Surface *exp_pic = 0;
234 int   exp_w, exp_h; /* size */
235 int   exp_frame_count; /* frame count */
236 typedef struct {
237     float alpha;
238     float cur; /* current frame */
239     int x, y; /* position in screen */
240 } Exp;
exp_load()241 void exp_load()
242 {
243     exps = list_create( LIST_AUTO_DELETE, LIST_NO_CALLBACK );
244     exp_pic = load_surf( "explosion.bmp", SDL_SWSURFACE );
245     exp_w = exp_h = exp_pic->h;
246     exp_frame_count = exp_pic->w / exp_w;
247 }
exps_clear()248 void exps_clear()
249 {
250     list_clear( exps );
251 }
exp_delete()252 void exp_delete()
253 {
254     if ( exp_pic )
255 	    SDL_FreeSurface( exp_pic );
256     exp_pic = 0;
257     if ( exps )
258 	    list_delete( exps );
259     exps = 0;
260 }
exp_create(int x,int y)261 void exp_create( int x, int y )
262 {
263     Exp *exp = calloc( 1, sizeof( Exp ) );
264     exp->x = x - ( exp_w >> 1 );
265     exp->y = y - ( exp_h >> 1 );
266     exp->alpha = 0;
267     list_add( exps, exp );
268 }
exps_hide()269 void exps_hide()
270 {
271     Exp *exp;
272     list_reset( exps );
273     while ( ( exp = list_next( exps ) ) ) {
274         DEST( sdl.screen, exp->x, exp->y, exp_w, exp_h );
275         SOURCE( offscreen, exp->x, exp->y );
276         blit_surf();
277         add_refresh_rect( exp->x, exp->y, exp_w, exp_h );
278     }
279 }
exps_show()280 void exps_show()
281 {
282     Exp *exp;
283     list_reset( exps );
284     while ( ( exp = list_next( exps ) ) ) {
285         DEST( sdl.screen, exp->x, exp->y, exp_w, exp_h );
286         SOURCE( exp_pic, (int)exp->cur * exp_w, 0 );
287         alpha_blit_surf( exp->alpha );
288     }
289 }
exps_update(int ms)290 void exps_update( int ms )
291 {
292     Exp *exp;
293     list_reset( exps );
294     while ( ( exp = list_next( exps ) ) ) {
295         if ( exp->alpha < 255 ) {
296             exp->alpha += exp_alpha_change * ms;
297             if ( exp->alpha > 255 ) exp->alpha = 255;
298         }
299         exp->cur += exp_change * ms;
300         if ( exp->cur >= exp_frame_count )
301             list_delete_current( exps );
302     }
303 }
304