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