1 /***************************************************************************
5 copyright : (C) 2001 by Michael Speck
6 email : kulkanie@gmx.net
7 ***************************************************************************/
9 /***************************************************************************
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. *
16 ***************************************************************************/
19 #include "lbreakout.h"
20 #include "../game/game.h"
25 extern SDL_Surface
*stk_display
, *nuke_bkgnd
, *brick_pic
;
26 extern Game
*local_game
, *game
;
27 extern Paddle
*l_paddle
;
29 extern SDL_Surface
*offscreen
;
30 extern int stk_quit_request
;
33 extern StkSound
*wav_click
;
35 extern int motion_button
;
37 extern int bkgnd_count
;
38 extern SDL_Surface
**bkgnds
;
41 ====================================================================
42 Load background according to id and draw background to offscreen.
43 Return Value: loaded background surface
44 ====================================================================
46 void bkgnd_draw( SDL_Surface
*bkgnd
, int id
, int to_offscreen
)
51 if ( id
>= bkgnd_count
|| id
== -1 )
52 id
= rand() % bkgnd_count
;
56 for ( i
= 0; i
< bkgnd
->w
; i
+= pic
->w
) {
57 for ( j
= 0; j
< bkgnd
->h
; j
+= pic
->h
) {
58 stk_surface_blit( pic
, 0,0,-1,-1,
63 /* draw to offscreen */
65 stk_surface_blit( bkgnd
, 0,0,-1,-1, offscreen
, 0,0 );
68 ====================================================================
69 Confirm request. Darkens screen a bit and display text.
70 Return Value: True if successful
71 ====================================================================
73 void draw_confirm_screen( StkFont
*font
, SDL_Surface
*buffer
, char *str
)
76 Text
*text
= create_text( str
, 60 );
77 stk_surface_fill( stk_display
, 0,0,-1,-1, 0x0 );
78 stk_surface_alpha_blit( buffer
, 0,0,-1,-1, stk_display
, 0,0, 128 );
79 font
->align
= STK_FONT_ALIGN_CENTER_X
| STK_FONT_ALIGN_TOP
;
80 y
= (stk_display
->h
- text
->count
* font
->height
) / 2;
81 x
= stk_display
->w
/ 2;
82 for ( i
= 0; i
< text
->count
; i
++ ) {
83 stk_font_write(font
, stk_display
, x
, y
, STK_OPAQUE
, text
->lines
[i
]);
88 int confirm( StkFont
*font
, char *str
, int type
)
94 stk_surface_create( SDL_SWSURFACE
, stk_display
->w
, stk_display
->h
);
95 SDL_SetColorKey(buffer
, 0, 0);
98 stk_sound_play( wav_click
);
101 event_clear_sdl_queue();
103 stk_surface_blit( stk_display
, 0,0,-1,-1, buffer
, 0,0 );
104 if ( type
== CONFIRM_PAUSE
)
105 stk_surface_gray( stk_display
, 0,0,-1,-1,0 );
107 draw_confirm_screen( font
, buffer
, str
);
108 stk_display_update( STK_UPDATE_ALL
);
110 while (go_on
&& !stk_quit_request
) {
111 SDL_WaitEvent(&event
);
113 switch ( event
.type
) {
114 case SDL_QUIT
: stk_quit_request
= 1; break;
115 case SDL_MOUSEBUTTONUP
:
116 if ( type
== CONFIRM_ANY_KEY
) {
120 if ( type == CONFIRM_YES_NO ) {
121 if ( event.button.button == LEFT_BUTTON )
129 if ( type
== CONFIRM_ANY_KEY
) {
134 if ( type
== CONFIRM_PAUSE
) {
135 if ( event
.key
.keysym
.sym
== SDLK_p
) {
140 if ( event
.key
.keysym
.sym
== SDLK_f
) {
141 config
.fullscreen
= !config
.fullscreen
;
142 stk_display_apply_fullscreen( config
.fullscreen
);
143 draw_confirm_screen( font
, buffer
, str
);
144 stk_display_update( STK_UPDATE_ALL
);
149 char *keyName
= SDL_GetKeyName(event
.key
.keysym
.sym
);
150 char *yesLetter
= _("y");
151 char *noLetter
= _("n");
152 if (strcmp(keyName
, yesLetter
) == 0) {
157 if (event
.key
.keysym
.sym
==SDLK_ESCAPE
|| strcmp(keyName
, noLetter
) == 0 ) {
168 stk_sound_play( wav_click
);
170 stk_surface_blit( buffer
, 0,0,-1,-1, stk_display
, 0,0 );
171 stk_display_update( STK_UPDATE_ALL
);
172 SDL_FreeSurface(buffer
);
174 /* reset the relative position so paddle wont jump */
175 SDL_GetRelativeMouseState(0,0);
179 #ifdef NETWORK_ENABLED
181 ====================================================================
182 Display a info message (gray screen a bit and display text),
183 send a MSG_READY when player has clicked and wait for a remote answer
184 (timeout 10 secs). Waiting may be cancelled by pressing ESCAPE which
185 results in sending a MSG_GAME_EXITED.
186 Return Value: True if both peers clicked to continue, False if the
187 connection was cancelled for some reason.
188 ====================================================================
190 int display_info( StkFont
*font
, char *str
, NetSocket
*peer
)
196 int ret
= 0, leave
= 0;
197 SDL_Surface
*buffer
=
198 stk_surface_create( SDL_SWSURFACE
, stk_display
->w
, stk_display
->h
);
199 SDL_SetColorKey(buffer
, 0, 0);
202 stk_sound_play( wav_click
);
205 event_clear_sdl_queue();
207 stk_surface_blit( stk_display
, 0,0,-1,-1, buffer
, 0,0 );
208 draw_confirm_screen( font
, buffer
, str
);
209 stk_display_update( STK_UPDATE_ALL
);
210 stk_wait_for_input();
211 net_write_empty_msg( peer
, MSG_READY
);
212 draw_confirm_screen( font
, buffer
,
213 _("Waiting for remote answer...") );
214 stk_display_update( STK_UPDATE_ALL
);
215 event_clear_sdl_queue();
217 if ( SDL_PollEvent( &event
) )
218 if ( (event
.type
== SDL_KEYDOWN
&&
219 event
.key
.keysym
.sym
== SDLK_ESCAPE
) ||
220 event
.type
== SDL_QUIT
) {
221 net_write_empty_msg( peer
, MSG_GAME_EXITED
);
225 if ( net_read_msg( peer
, &msg
, 0 ) )
226 switch ( msg
.type
) {
230 case MSG_GAME_EXITED
:
232 sprintf( error
, /* xgettext:no-c-format */ _("remote player cancelled the game\n") );
233 confirm( font
, error
, CONFIRM_ANY_KEY
);
240 stk_sound_play( wav_click
);
243 stk_surface_blit( buffer
, 0,0,-1,-1, stk_display
, 0,0 );
244 stk_display_update( STK_UPDATE_ALL
);
245 SDL_FreeSurface(buffer
);
247 /* reset the relative position so paddle wont jump */
248 SDL_GetRelativeMouseState(0,0);
256 ====================================================================
257 Create shadow surface for specified region in surface.
258 Return Value: Shadow surface
259 ====================================================================
261 SDL_Surface
* create_shadow( SDL_Surface
*surf
, int x
, int y
, int w
, int h
)
263 SDL_Surface
*shadow
= 0;
265 Uint32 white
= SDL_MapRGB( stk_display
->format
, 0xff, 0xff, 0xff );
266 Uint32 black
= SDL_MapRGB( stk_display
->format
, 0, 0, 0 );
267 shadow
= stk_surface_create( SDL_SWSURFACE
, w
, h
);
268 SDL_SetColorKey( shadow
, SDL_SRCCOLORKEY
, white
);
269 for ( i
= 0; i
< w
; i
++ )
270 for ( j
= 0; j
< h
; j
++ ) {
271 if ( surf
->flags
& SDL_SRCCOLORKEY
&&
272 stk_surface_get_pixel( surf
, i
, j
) == surf
->format
->colorkey
)
273 stk_surface_set_pixel( shadow
, i
, j
, white
);
275 stk_surface_set_pixel( shadow
, i
, j
, black
);
282 ====================================================================
283 Enter a string and return True if ENTER received and False
285 ====================================================================
287 int enter_string( StkFont
*font
, char *caption
, char *edit
, int limit
)
292 SDL_Surface
*buffer
=
293 stk_surface_create( SDL_SWSURFACE
, stk_display
->w
, stk_display
->h
);
294 int length
= strlen( edit
);
296 SDL_SetColorKey(buffer
, 0, 0);
298 stk_surface_blit( stk_display
, 0,0,-1,-1, buffer
, 0,0 );
299 font
->align
= STK_FONT_ALIGN_CENTER_X
| STK_FONT_ALIGN_CENTER_Y
;
301 while ( go_on
&& !stk_quit_request
) {
303 stk_surface_fill( stk_display
, 0,0,-1,-1, 0x0 );
304 stk_surface_alpha_blit( buffer
, 0,0,-1,-1, stk_display
, 0,0, 128 );
305 stk_font_write(font
, stk_display
, stk_display
->w
/ 2, stk_display
->h
/ 2, STK_OPAQUE
, caption
);
306 write_text_with_cursor(font
, stk_display
, stk_display
->w
/ 2, stk_display
->h
/ 2 + font
->height
, edit
, STK_OPAQUE
);
307 stk_display_update( STK_UPDATE_ALL
);
308 event
.type
= SDL_NOEVENT
;
309 SDL_PollEvent(&event
);
311 switch ( event
.type
) {
312 case SDL_QUIT
: stk_quit_request
= 1; break;
314 switch ( event
.key
.keysym
.sym
) {
324 if ( length
> 0 ) edit
[--length
] = 0;
327 if ( event
.key
.keysym
.sym
>= 32 && event
.key
.keysym
.sym
< 128 && length
< limit
) {
328 edit
[length
++] = event
.key
.keysym
.unicode
;
336 stk_surface_blit( buffer
, 0,0,-1,-1, stk_display
, 0,0 );
337 stk_display_update( STK_UPDATE_ALL
);
338 SDL_FreeSurface(buffer
);
340 /* reset the relative position so paddle wont jump */
341 SDL_GetRelativeMouseState(0,0);
347 ====================================================================
348 Display text blinking.
349 ====================================================================
351 void write_text_with_cursor( StkFont
*fnt
, SDL_Surface
*dest
,
352 int x
, int y
, char *str
, int alpha
)
354 static int cursor_on
= 0;
355 static Uint32 last_tick
= 0;
356 // create temporary space for cursor and text
357 char *text_with_cursor
= calloc(strlen(str
) + 2, sizeof(char));
358 if (text_with_cursor
) {
359 strcpy(text_with_cursor
, str
);
361 // Time to blink cursor on/off?
362 if (SDL_GetTicks() - last_tick
> 500) {
363 last_tick
= SDL_GetTicks();
364 cursor_on
= ! cursor_on
;
366 // Tack on cursor to end of text
368 strcat(text_with_cursor
, "_");
371 strcat(text_with_cursor
, " ");
374 stk_font_write(fnt
,dest
,x
,y
,alpha
,text_with_cursor
);
376 free(text_with_cursor
);
381 ====================================================================
382 Enter nuke mode and allow player to disintegrate single bricks
383 by spending 5% of his/her score.
384 ====================================================================
386 void game_nuke( void )
390 int x
,y
,i
,j
,leave
= 0;
391 SDL_Surface
*buffer
=
392 stk_surface_create( SDL_SWSURFACE
, stk_display
->w
, stk_display
->h
);
393 SDL_Surface
*red_mask
=
394 stk_surface_create( SDL_SWSURFACE
, BRICK_WIDTH
, BRICK_HEIGHT
);
395 stk_surface_fill( red_mask
, 0,0,-1,-1, 0xFF0000 );
396 SDL_SetAlpha( red_mask
, SDL_SRCALPHA
, 128 );
397 SDL_SetColorKey(buffer
, 0, 0);
400 stk_sound_play( wav_click
);
402 SDL_SetEventFilter(0);
403 event_clear_sdl_queue();
404 /* backup screen contents */
405 stk_surface_blit( stk_display
, 0,0,-1,-1, buffer
, 0,0 );
406 /* display bricks darkened */
407 stk_surface_blit( nuke_bkgnd
, 0,0,-1,-1,
409 for ( i
= 1; i
< MAP_WIDTH
- 1; i
++ )
410 for ( j
= 1; j
< MAP_HEIGHT
- 1; j
++ )
411 if ( game
->bricks
[i
][j
].id
>= 0 )
412 stk_surface_alpha_blit( brick_pic
,
413 game
->bricks
[i
][j
].id
* BRICK_WIDTH
, 0,
414 BRICK_WIDTH
, BRICK_HEIGHT
,
416 i
*BRICK_WIDTH
, j
*BRICK_HEIGHT
, 128 );
418 font
->align
= STK_FONT_ALIGN_LEFT
;
419 sprintf( buf
, _("Plane Of Inner Stability entered (Score: %i)"),
420 l_paddle
->player
->stats
.total_score
+ l_paddle
->score
);
421 stk_font_write( font
, stk_display
,
422 BRICK_WIDTH
, (MAP_HEIGHT
-1)*BRICK_HEIGHT
,
424 /* show score of player */
425 stk_display_update( STK_UPDATE_ALL
);
428 while (!leave
&& !stk_quit_request
) {
429 SDL_WaitEvent(&event
);
430 switch ( event
.type
) {
432 stk_quit_request
= 1;
434 case SDL_MOUSEBUTTONDOWN
:
437 /* xgettext:no-c-format */ _("Disintegrate Brick? (Costs 5% of your score.) y/n"),
439 /* implant a bomb to this brick and return */
440 game_set_current( local_game
);
441 brick_start_expl( x
,y
, BRICK_EXP_TIME
,
442 local_game
->paddles
[0] );
443 local_game
->bricks
[x
][y
].score
= 0;
444 game_set_current( game
);
445 l_paddle
->player
->stats
.total_score
-= (int)(0.05 *
447 l_paddle
->player
->stats
.total_score
));
451 case SDL_MOUSEMOTION
:
453 /* clear old selection */
454 stk_surface_blit( nuke_bkgnd
,
455 x
*BRICK_WIDTH
, y
*BRICK_HEIGHT
,
456 BRICK_WIDTH
, BRICK_HEIGHT
,
458 x
*BRICK_WIDTH
, y
*BRICK_HEIGHT
);
459 stk_surface_alpha_blit( brick_pic
,
460 game
->bricks
[x
][y
].id
* BRICK_WIDTH
, 0,
461 BRICK_WIDTH
, BRICK_HEIGHT
,
463 x
*BRICK_WIDTH
, y
*BRICK_HEIGHT
, 128 );
464 stk_display_store_drect();
467 /* make new selection if brick */
468 i
= event
.motion
.x
/ BRICK_WIDTH
;
469 j
= event
.motion
.y
/ BRICK_HEIGHT
;
470 if ( i
>= 1 && i
<= MAP_WIDTH
-2 )
471 if ( j
>= 1 && j
<= MAP_HEIGHT
- 2 )
472 if ( game
->bricks
[i
][j
].id
>= 0 ) {
474 stk_surface_blit( red_mask
, 0,0,-1,-1,
475 stk_display
,x
*BRICK_WIDTH
, y
*BRICK_HEIGHT
);
476 stk_display_store_drect();
480 if ( event
.key
.keysym
.sym
== SDLK_ESCAPE
)
484 stk_display_update( STK_UPDATE_RECTS
);
487 stk_surface_blit( buffer
, 0,0,-1,-1, stk_display
, 0,0 );
488 stk_display_update( STK_UPDATE_ALL
);
489 SDL_FreeSurface(red_mask
);
490 SDL_FreeSurface(buffer
);
491 SDL_SetEventFilter(event_filter
);
494 /* gray screen and display a formatted text, directly update the
496 void display_text( StkFont
*font
, char *format
, ... )
503 va_start( args
, format
);
504 vsnprintf( buf
, 512, format
, args
);
507 stk_surface_gray( stk_display
, 0,0,-1,-1, 2 );
508 text
= create_text( buf
, 60 );
509 font
->align
= STK_FONT_ALIGN_CENTER_X
| STK_FONT_ALIGN_TOP
;
510 y
= (stk_display
->h
- text
->count
* font
->height
) / 2;
511 x
= stk_display
->w
/ 2;
512 for ( i
= 0; i
< text
->count
; i
++ ) {
513 stk_font_write(font
, stk_display
, x
, y
, STK_OPAQUE
, text
->lines
[i
]);
518 stk_display_update( STK_UPDATE_ALL
);