1 /***************************************************************************
2                           frame.c  -  description
3                              -------------------
4     begin                : Fri Sep 7 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 "lbreakout.h"
19 #include "config.h"
20 #include "player.h"
21 #include "display.h"
22 #include "frame.h"
23 
24 extern SDL_Surface *stk_display;
25 extern SDL_Surface *offscreen;
26 extern SDL_Surface *bkgnd; /* background + frame */
27 extern SDL_Surface *brick_pic; /* brick graphics in a horizontal order */
28 /* parts of the frame: left, top, right */
29 extern SDL_Surface *frame_left, *frame_top, *frame_right;
30 extern SDL_Surface *frame_left_shadow, *frame_top_shadow, *frame_right_shadow;
31 extern SDL_Surface *frame_mp_left, *frame_mp_right;
32 extern SDL_Surface *frame_mp_left_shadow, *frame_mp_right_shadow;
33 extern SDL_Surface *lamps; /* life lamps */
34 float score = 0; /* current score */
35 int dest_score; /* final score */
36 int score_x_offset = 54; /* display score at this position (right align)*/
37 int score_x, score_y = BRICK_HEIGHT / 2 - 2; /* center position where to write score */
38 int new_life_y; /* if new life lamp is drawn do this at this y position */
39 int name_x = 404, name_y = BRICK_HEIGHT / 2 - 2; /* offset (right side of screen) */
40 extern int shadow_size;
41 extern Config config;
42 int info_x;
43 int info_y; /* absolute position is info_y + info_offset */
44 int info_offsets[EX_NUMBER]; /* offset at which extra info is displayed */
45 int paddle_info_y[4];
46 int paddle_info_offsets[EX_NUMBER]; /* specialized extras */
47 extern SDL_Surface *extra_pic;
48 #ifdef AUDIO_ENABLED
49 extern StkSound *wav_life_up, *wav_life_down;
50 #endif
51 extern StkFont *display_font;
52 int warp_blink;
53 Delay warp_delay;
54 int warp_x, warp_y;
55 int warp_blinks;
56 extern SDL_Surface *warp_pic;
57 extern Game *game;
58 
59 /*
60 ====================================================================
61 Locals
62 ====================================================================
63 */
64 
65 /*
66 ====================================================================
67 Publics
68 ====================================================================
69 */
70 
71 /*
72 ====================================================================
73 Create frame by loading and assembling all graphics and loading
74 additional graphics.
75 ====================================================================
76 */
frame_create()77 void frame_create()
78 {
79     delay_set( &warp_delay, 500 );
80     warp_x = stk_display->w - BRICK_WIDTH + ( BRICK_WIDTH - warp_pic->w ) / 2;
81     warp_y = stk_display->h - warp_pic->h;
82     warp_blink = 0;
83 }
84 
85 /*
86 ====================================================================
87 Inititate the frame to the according game type.
88 Set the position of the extras displayed, enable life lamps etc.
89 ====================================================================
90 */
frame_init()91 void frame_init()
92 {
93     /* setup position of extra info */
94     info_x = stk_display->w - BRICK_WIDTH;
95     if ( game->game_type == GT_NETWORK ) {
96         /* general */
97         info_y = 178;
98         info_offsets[EX_METAL] = 26;
99         info_offsets[EX_WEAK_BALL] = 26;
100         info_offsets[EX_EXPL_BALL] = 26;
101         info_offsets[EX_FAST] = 52;
102         info_offsets[EX_SLOW] = 52;
103         info_offsets[EX_CHAOS] = 78;
104         /* paddles */
105         paddle_info_y[0] = 271;
106         paddle_info_y[1] = 7;
107         paddle_info_offsets[EX_SLIME] = 26;
108         paddle_info_offsets[EX_WEAPON] = 52;
109         paddle_info_offsets[EX_WALL] = 78;
110         paddle_info_offsets[EX_GOLDSHOWER] = 104;
111         paddle_info_offsets[EX_GHOST_PADDLE] = 130;
112         paddle_info_offsets[EX_BONUS_MAGNET] = 156;
113         paddle_info_offsets[EX_MALUS_MAGNET] = 156;
114     }
115     else {
116         /* in single player we ignore the second paddle
117            and model general and paddle0 extras so that
118            they result in the old layout */
119         info_y = 48; paddle_info_y[0] = 48;
120         paddle_info_offsets[EX_GOLDSHOWER] = 30;
121         paddle_info_offsets[EX_SLIME] = 60;
122         info_offsets[EX_METAL] = 90;
123         info_offsets[EX_WEAK_BALL] = 90;
124         info_offsets[EX_EXPL_BALL] = 90;
125         paddle_info_offsets[EX_WALL] = 120;
126         paddle_info_offsets[EX_WEAPON] = 150;
127         info_offsets[EX_FAST] = 180;
128         info_offsets[EX_SLOW] = 180;
129         info_offsets[EX_CHAOS] = 210;
130         paddle_info_offsets[EX_GHOST_PADDLE] = 240;
131         paddle_info_offsets[EX_BONUS_MAGNET] = 270;
132         paddle_info_offsets[EX_MALUS_MAGNET] = 270;
133     }
134 }
135 
136 /*
137 ====================================================================
138 Free all resources created by frame_create()
139 ====================================================================
140 */
frame_delete()141 void frame_delete()
142 {
143 }
144 /*
145 ====================================================================
146 Draw frame to offscreen and to bkgnd as frame won't change while
147 playing.
148 ====================================================================
149 */
frame_draw()150 void frame_draw()
151 {
152     SDL_Surface *fr_left = (game->game_type==GT_LOCAL)?frame_left:frame_mp_left;
153     SDL_Surface *fr_right = (game->game_type==GT_LOCAL)?frame_right:frame_mp_right;
154     SDL_Surface *fr_left_shadow =
155 	    (game->game_type==GT_LOCAL)?frame_left_shadow:frame_mp_left_shadow;
156     SDL_Surface *fr_right_shadow =
157 	    (game->game_type==GT_LOCAL)?frame_right_shadow:frame_mp_right_shadow;
158     /* left and right part are always drawn */
159     /* left part */
160     stk_surface_alpha_blit( fr_left_shadow, 0,0,-1,-1,
161         offscreen, shadow_size, shadow_size, SHADOW_ALPHA );
162     stk_surface_blit( fr_left, 0,0,-1,-1, offscreen, 0,0 );
163     stk_surface_alpha_blit( fr_left_shadow, 0,0,-1,-1,
164         bkgnd, shadow_size, shadow_size, SHADOW_ALPHA );
165     stk_surface_blit( fr_left, 0,0,-1,-1, bkgnd, 0,0 );
166     if ( game->game_type == GT_LOCAL ) {
167         /* add top */
168         stk_surface_alpha_blit( frame_top_shadow, 0,0,-1,-1,
169             offscreen, fr_left->w + shadow_size, shadow_size, SHADOW_ALPHA );
170         stk_surface_blit(
171             frame_top, 0,0,-1,-1, offscreen, fr_left->w,0 );
172         stk_surface_alpha_blit( frame_top_shadow, 0,0,-1,-1,
173             bkgnd, fr_left->w + shadow_size, shadow_size, SHADOW_ALPHA );
174         stk_surface_blit(
175             frame_top, 0,0,-1,-1, bkgnd, fr_left->w,0 );
176     }
177     /* right part */
178     stk_surface_alpha_blit( fr_right_shadow, 0,0,-1,-1,
179         offscreen, stk_display->w - fr_right_shadow->w + shadow_size,
180         shadow_size, SHADOW_ALPHA );
181     stk_surface_blit( fr_right, 0,0,-1,-1, offscreen,
182         stk_display->w - fr_right->w,0 );
183     stk_surface_alpha_blit( fr_right_shadow, 0,0,-1,-1,
184         bkgnd, stk_display->w - fr_right_shadow->w + shadow_size,
185         shadow_size, SHADOW_ALPHA );
186     stk_surface_blit( fr_right, 0,0,-1,-1, bkgnd,
187         stk_display->w - fr_right->w,0 );
188 }
189 /*
190 ====================================================================
191 Add life lamps at left side of frame in offscreen
192 ====================================================================
193 */
frame_draw_lives(int lives,int max_lives)194 void frame_draw_lives( int lives, int max_lives )
195 {
196     int i,y;
197     /* substract one life to have the same result like in old LBreakout */
198     /* at maximum ten lamps may be displayed */
199     for ( i = 0; i < 10; i++ ) {
200         if ( i < lives - 1 )
201             y = BRICK_HEIGHT;
202         else
203             if ( i < max_lives - 1 )
204                 y = 0;
205             else
206                 y = BRICK_HEIGHT * 2;
207         stk_surface_blit( lamps, 0,y, BRICK_WIDTH, BRICK_HEIGHT,
208             offscreen, 0, ( MAP_HEIGHT - i - 1 ) * BRICK_HEIGHT );
209     }
210     /* get position of next lamp */
211     new_life_y = stk_display->h - lives * BRICK_HEIGHT;
212 }
213 /*
214 ====================================================================
215 Add one new life at offscreen and screen (as this will happen in
216 game )
217 ====================================================================
218 */
frame_add_life()219 void frame_add_life()
220 {
221 	if ( !game->extra_active[EX_DARKNESS] ) {
222         stk_surface_blit( lamps, 0, BRICK_HEIGHT,
223             BRICK_WIDTH, BRICK_HEIGHT,
224             stk_display, 0, new_life_y );
225         stk_display_store_drect();
226 	}
227     new_life_y -= BRICK_HEIGHT;
228 #ifdef AUDIO_ENABLED
229     stk_sound_play_x( 20, wav_life_up );
230 #endif
231 }
232 /*
233 ====================================================================
234 Switch of a life lamp
235 ====================================================================
236 */
frame_remove_life()237 void frame_remove_life()
238 {
239     new_life_y += BRICK_HEIGHT;
240     if ( new_life_y >= stk_display->h ) return;
241 	if ( !game->extra_active[EX_DARKNESS] ) {
242         stk_surface_blit( lamps, 0, 0, BRICK_WIDTH, BRICK_HEIGHT,
243             stk_display, 0, new_life_y );
244         stk_display_store_drect();
245 	}
246 #ifdef AUDIO_ENABLED
247     stk_sound_play_x( 20, wav_life_down );
248 #endif
249 }
250 /*
251 ====================================================================
252 Display extra information on right side of screen.
253 ====================================================================
254 */
frame_info_hide()255 void frame_info_hide()
256 {
257     int i, j;
258     if ( !config.bonus_info ) return;
259     for ( i = 0; i < EX_NUMBER; i++ )
260         if ( info_offsets[i] > 0 && game->extra_active[i] ) {
261             stk_surface_blit( offscreen, info_x, info_y + info_offsets[i],
262                 BRICK_WIDTH, BRICK_HEIGHT,
263                 stk_display, info_x, info_y + info_offsets[i] );
264             stk_display_store_drect();
265         }
266     for ( i = 0; i < EX_NUMBER; i++ )
267         for ( j = 0; j < game->paddle_count; j++ )
268             if ( paddle_info_offsets[i] > 0 && game->paddles[j]->extra_active[i] ) {
269                 stk_surface_blit( offscreen, info_x,
270                     paddle_info_y[j] + paddle_info_offsets[i],
271                     BRICK_WIDTH, BRICK_HEIGHT,
272                     stk_display, info_x, paddle_info_y[j] + paddle_info_offsets[i] );
273                 stk_display_store_drect();
274             }
275 }
frame_info_show()276 void frame_info_show()
277 {
278     char str[12];
279     int i, j;
280     if ( !config.bonus_info ) return;
281     display_font->align = STK_FONT_ALIGN_CENTER_X | STK_FONT_ALIGN_CENTER_Y;
282     for ( i = 0; i < EX_NUMBER; i++ ) {
283         if ( info_offsets[i] > 0 && game->extra_active[i] ) {
284             /* picture */
285             stk_surface_fill(
286                 stk_display, info_x, info_y + info_offsets[i],
287                 BRICK_WIDTH, BRICK_HEIGHT, 0x0 );
288             stk_surface_alpha_blit( extra_pic, i * BRICK_WIDTH, 0,
289                 BRICK_WIDTH, BRICK_HEIGHT,
290                 stk_display, info_x, info_y + info_offsets[i], 128 );
291             /* remaining extra_time */
292             sprintf(str, "%i", (game->extra_time[i] / 1000) + 1);
293             /* write text */
294             stk_font_write( display_font, stk_display,
295                         info_x + ( BRICK_WIDTH >> 1 ), info_y + info_offsets[i] + ( BRICK_HEIGHT >> 1 ),
296                         -1, str );
297         }
298 	}
299     for ( i = 0; i < EX_NUMBER; i++ )
300         for ( j = 0; j < game->paddle_count; j++ )
301             if ( paddle_info_offsets[i] > 0 && game->paddles[j]->extra_active[i] ) {
302                 if ( i == EX_WALL && game->paddles[j]->extra_time[i] <= 0 ) continue;
303                 /* picture */
304                 stk_surface_fill(
305                     stk_display, info_x, paddle_info_y[j] + paddle_info_offsets[i],
306                     BRICK_WIDTH, BRICK_HEIGHT, 0x0 );
307                 stk_surface_alpha_blit( extra_pic, i * BRICK_WIDTH, 0,
308                     BRICK_WIDTH, BRICK_HEIGHT,
309                     stk_display, info_x, paddle_info_y[j] + paddle_info_offsets[i], 128 );
310                 /* remaining extra_time */
311                 sprintf(str, "%i", (game->paddles[j]->extra_time[i] / 1000) + 1);
312                 /* write text */
313                 stk_font_write( display_font, stk_display,
314                             info_x + ( BRICK_WIDTH >> 1 ),
315                             paddle_info_y[j] + paddle_info_offsets[i] + ( BRICK_HEIGHT >> 1 ),
316                             -1, str );
317             }
318 }
319 
320 /*
321 ====================================================================
322 Blink the warp icon.
323 ====================================================================
324 */
frame_warp_icon_hide()325 void frame_warp_icon_hide()
326 {
327         if ( game->game_type != GT_LOCAL ) return;
328 	if ( game->level_type == LT_PINGPONG ) return;
329 	if ( game->bricks_left > game->warp_limit ) return;
330 	stk_surface_blit( offscreen, warp_x,warp_y,-1,-1,
331 			stk_display, warp_x, warp_y );
332 	stk_display_store_drect();
333 }
frame_warp_icon_show()334 void frame_warp_icon_show()
335 {
336         if ( game->game_type != GT_LOCAL ) return;
337 	if ( game->level_type == LT_PINGPONG ) return;
338 	if ( game->warp_limit == 0 ) return;
339 	if ( game->bricks_left > game->warp_limit ) return;
340 	if ( !warp_blink ) return;
341 	if ( !game->extra_active[EX_DARKNESS] )
342 		stk_surface_blit( warp_pic, 0,0,-1,-1,
343 				stk_display, warp_x, warp_y );
344 	else
345 		stk_surface_alpha_blit( warp_pic, 0,0,-1,-1,
346 				stk_display, warp_x, warp_y, 128 );
347 }
frame_warp_icon_update(int ms)348 void frame_warp_icon_update( int ms )
349 {
350 	//printf( "%i > %i\n", game->bricks_left, game->warp_limit );
351         if ( game->game_type != GT_LOCAL ) return;
352 	if ( game->level_type == LT_PINGPONG ) return;
353 	if ( game->bricks_left > game->warp_limit ) return;
354 	if ( warp_blinks == 0 ) {
355 		warp_blink = 1;
356 		return;
357 	}
358 	if ( delay_timed_out( &warp_delay, ms ) ) {
359 		warp_blink = !warp_blink;
360 		if ( warp_blink )
361 			warp_blinks--;
362 	}
363 }
364