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