Files
commandergenius/project/jni/application/lbreakout2/client/misc.c
2010-09-16 17:23:34 +03:00

519 lines
16 KiB
C

/***************************************************************************
misc.c - description
-------------------
begin : Thu Sep 6 2001
copyright : (C) 2001 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <time.h>
#include "lbreakout.h"
#include "../game/game.h"
#include "config.h"
#include "event.h"
#include "misc.h"
extern SDL_Surface *stk_display, *nuke_bkgnd, *brick_pic;
extern Game *local_game, *game;
extern Paddle *l_paddle;
extern StkFont *font;
extern SDL_Surface *offscreen;
extern int stk_quit_request;
int shadow_size = 8;
#ifdef AUDIO_ENABLED
extern StkSound *wav_click;
#endif
extern int motion_button;
extern Config config;
extern int bkgnd_count;
extern SDL_Surface **bkgnds;
/*
====================================================================
Load background according to id and draw background to offscreen.
Return Value: loaded background surface
====================================================================
*/
void bkgnd_draw( SDL_Surface *bkgnd, int id )
{
SDL_Surface *pic = 0;
int i, j;
if ( id >= bkgnd_count || id == -1 )
id = rand() % bkgnd_count;
/* load background */
pic = bkgnds[id];
for ( i = 0; i < bkgnd->w; i += pic->w ) {
for ( j = 0; j < bkgnd->h; j += pic->h ) {
stk_surface_blit( pic, 0,0,-1,-1,
bkgnd, i, j);
}
}
/* draw to offscreen */
stk_surface_blit( bkgnd, 0,0,-1,-1, stk_display, 0,0 );
}
/*
====================================================================
Confirm request. Darkens screen a bit and display text.
Return Value: True if successful
====================================================================
*/
void draw_confirm_screen( StkFont *font, SDL_Surface *buffer, char *str )
{
int i, y, x;
Text *text = create_text( str, 60 );
stk_surface_fill( stk_display, 0,0,-1,-1, 0x0 );
stk_surface_alpha_blit( buffer, 0,0,-1,-1, stk_display, 0,0, 128 );
font->align = STK_FONT_ALIGN_CENTER_X | STK_FONT_ALIGN_TOP;
y = (stk_display->h - text->count * font->height) / 2;
x = stk_display->w / 2;
for ( i = 0; i < text->count; i++ ) {
stk_font_write(font, stk_display, x, y, STK_OPAQUE, text->lines[i]);
y += font->height;
}
delete_text( text );
}
int confirm( StkFont *font, char *str, int type )
{
SDL_Event event;
int go_on = 1;
int ret = 0;
SDL_Surface *buffer =
stk_surface_create( SDL_SWSURFACE, stk_display->w, stk_display->h );
SDL_SetColorKey(buffer, 0, 0);
#ifdef AUDIO_ENABLED
stk_sound_play( wav_click );
#endif
event_clear_sdl_queue();
stk_surface_blit( stk_display, 0,0,-1,-1, buffer, 0,0 );
if ( type == CONFIRM_PAUSE )
stk_surface_gray( stk_display, 0,0,-1,-1,0 );
else
draw_confirm_screen( font, buffer, str );
stk_display_update( STK_UPDATE_ALL );
while (go_on && !stk_quit_request) {
SDL_WaitEvent(&event);
/* TEST */
switch ( event.type ) {
case SDL_QUIT: stk_quit_request = 1; break;
case SDL_MOUSEBUTTONUP:
if ( type == CONFIRM_ANY_KEY ) {
ret = 1; go_on = 0;
}
/* else
if ( type == CONFIRM_YES_NO ) {
if ( event.button.button == LEFT_BUTTON )
ret = 1;
else
ret = 0;
go_on = 0;
}*/
break;
case SDL_KEYDOWN:
if ( type == CONFIRM_ANY_KEY ) {
ret = 1; go_on = 0;
break;
}
else
if ( type == CONFIRM_PAUSE ) {
if ( event.key.keysym.sym == SDLK_p ) {
ret = 1; go_on = 0;
break;
}
else
if ( event.key.keysym.sym == SDLK_f ) {
config.fullscreen = !config.fullscreen;
stk_display_apply_fullscreen( config.fullscreen );
draw_confirm_screen( font, buffer, str );
stk_display_update( STK_UPDATE_ALL );
}
}
else
{
char *keyName = SDL_GetKeyName(event.key.keysym.sym);
char *yesLetter = _("y");
char *noLetter = _("n");
if (strcmp(keyName, yesLetter) == 0) {
go_on = 0;
ret = 1;
}
else
if (event.key.keysym.sym==SDLK_ESCAPE || strcmp(keyName, noLetter) == 0 ) {
go_on = 0;
ret = 0;
}
default:
break;
}
break;
}
}
#ifdef AUDIO_ENABLED
stk_sound_play( wav_click );
#endif
stk_surface_blit( buffer, 0,0,-1,-1, stk_display, 0,0 );
stk_display_update( STK_UPDATE_ALL );
SDL_FreeSurface(buffer);
/* reset the relative position so paddle wont jump */
SDL_GetRelativeMouseState(0,0);
return ret;
}
#ifdef NETWORK_ENABLED
/*
====================================================================
Display a info message (gray screen a bit and display text),
send a MSG_READY when player has clicked and wait for a remote answer
(timeout 10 secs). Waiting may be cancelled by pressing ESCAPE which
results in sending a MSG_GAME_EXITED.
Return Value: True if both peers clicked to continue, False if the
connection was cancelled for some reason.
====================================================================
*/
int display_info( StkFont *font, char *str, NetSocket *peer )
{
#if 0
char error[128];
Net_Msg msg;
SDL_Event event;
int ret = 0, leave = 0;
SDL_Surface *buffer =
stk_surface_create( SDL_SWSURFACE, stk_display->w, stk_display->h );
SDL_SetColorKey(buffer, 0, 0);
#ifdef AUDIO_ENABLED
stk_sound_play( wav_click );
#endif
event_clear_sdl_queue();
stk_surface_blit( stk_display, 0,0,-1,-1, buffer, 0,0 );
draw_confirm_screen( font, buffer, str );
stk_display_update( STK_UPDATE_ALL );
stk_wait_for_input();
net_write_empty_msg( peer, MSG_READY );
draw_confirm_screen( font, buffer,
_("Waiting for remote answer...") );
stk_display_update( STK_UPDATE_ALL );
event_clear_sdl_queue();
while ( !leave ) {
if ( SDL_PollEvent( &event ) )
if ( (event.type == SDL_KEYDOWN &&
event.key.keysym.sym == SDLK_ESCAPE) ||
event.type == SDL_QUIT ) {
net_write_empty_msg( peer, MSG_GAME_EXITED );
leave = 1;
break;
}
if ( net_read_msg( peer, &msg, 0 ) )
switch ( msg.type ) {
case MSG_READY:
ret = 1; leave = 1;
break;
case MSG_GAME_EXITED:
ret = 0; leave = 1;
sprintf( error, /* xgettext:no-c-format */ _("remote player cancelled the game\n") );
confirm( font, error, CONFIRM_ANY_KEY );
break;
}
SDL_Delay( 10 );
}
#ifdef AUDIO_ENABLED
stk_sound_play( wav_click );
#endif
stk_surface_blit( buffer, 0,0,-1,-1, stk_display, 0,0 );
stk_display_update( STK_UPDATE_ALL );
SDL_FreeSurface(buffer);
/* reset the relative position so paddle wont jump */
SDL_GetRelativeMouseState(0,0);
return ret;
#endif
return 1;
}
#endif
/*
====================================================================
Create shadow surface for specified region in surface.
Return Value: Shadow surface
====================================================================
*/
SDL_Surface* create_shadow( SDL_Surface *surf, int x, int y, int w, int h )
{
SDL_Surface *shadow = 0;
int i, j;
Uint32 white = SDL_MapRGB( stk_display->format, 0xff, 0xff, 0xff );
Uint32 black = SDL_MapRGB( stk_display->format, 0, 0, 0 );
shadow = stk_surface_create( SDL_SWSURFACE, w, h );
SDL_SetColorKey( shadow, SDL_SRCCOLORKEY, white );
for ( i = 0; i < w; i++ )
for ( j = 0; j < h; j++ ) {
if ( surf->flags & SDL_SRCCOLORKEY &&
stk_surface_get_pixel( surf, i, j ) == surf->format->colorkey )
stk_surface_set_pixel( shadow, i, j, white );
else
stk_surface_set_pixel( shadow, i, j, black );
}
return shadow;
}
/*
====================================================================
Enter a string and return True if ENTER received and False
if ESCAPE received.
====================================================================
*/
int enter_string( StkFont *font, char *caption, char *edit, int limit )
{
SDL_Event event;
int go_on = 1;
int ret = 0;
SDL_Surface *buffer =
stk_surface_create( SDL_SWSURFACE, stk_display->w, stk_display->h );
int length = strlen( edit );
SDL_SetColorKey(buffer, 0, 0);
stk_surface_blit( stk_display, 0,0,-1,-1, buffer, 0,0 );
font->align = STK_FONT_ALIGN_CENTER_X | STK_FONT_ALIGN_CENTER_Y;
while ( go_on && !stk_quit_request ) {
stk_surface_fill( stk_display, 0,0,-1,-1, 0x0 );
stk_surface_alpha_blit( buffer, 0,0,-1,-1, stk_display, 0,0, 128 );
stk_font_write(font, stk_display, stk_display->w / 2, stk_display->h / 2, STK_OPAQUE, caption);
write_text_with_cursor(font, stk_display, stk_display->w / 2, stk_display->h / 2 + font->height, edit, STK_OPAQUE);
stk_display_update( STK_UPDATE_ALL );
event.type = SDL_NOEVENT;
SDL_PollEvent(&event);
/* TEST */
switch ( event.type ) {
case SDL_QUIT: stk_quit_request = 1; break;
case SDL_KEYDOWN:
switch ( event.key.keysym.sym ) {
case SDLK_ESCAPE:
ret = 0;
go_on = 0;
break;
case SDLK_RETURN:
ret = 1;
go_on = 0;
break;
case SDLK_BACKSPACE:
if ( length > 0 ) edit[--length] = 0;
break;
default:
if ( event.key.keysym.sym >= 32 && event.key.keysym.sym < 128 && length < limit ) {
edit[length++] = event.key.keysym.unicode;
edit[length] = 0;
}
break;
}
break;
}
}
stk_surface_blit( buffer, 0,0,-1,-1, stk_display, 0,0 );
stk_display_update( STK_UPDATE_ALL );
SDL_FreeSurface(buffer);
/* reset the relative position so paddle wont jump */
SDL_GetRelativeMouseState(0,0);
return ret;
}
/*
====================================================================
Display text blinking.
====================================================================
*/
void write_text_with_cursor( StkFont *fnt, SDL_Surface *dest,
int x, int y, char *str, int alpha)
{
static int cursor_on = 0;
static Uint32 last_tick = 0;
// create temporary space for cursor and text
char *text_with_cursor = calloc(strlen(str) + 2, sizeof(char));
if (text_with_cursor) {
strcpy(text_with_cursor, str);
// Time to blink cursor on/off?
if (SDL_GetTicks() - last_tick > 500) {
last_tick = SDL_GetTicks();
cursor_on = ! cursor_on;
}
// Tack on cursor to end of text
if (cursor_on) {
strcat(text_with_cursor, "_");
}
else {
strcat(text_with_cursor, " ");
}
stk_font_write(fnt,dest,x,y,alpha,text_with_cursor);
free(text_with_cursor);
}
}
/*
====================================================================
Enter nuke mode and allow player to disintegrate single bricks
by spending 5% of his/her score.
====================================================================
*/
void game_nuke( void )
{
char buf[128];
SDL_Event event;
int x,y,i,j,leave = 0;
SDL_Surface *buffer =
stk_surface_create( SDL_SWSURFACE, stk_display->w, stk_display->h );
SDL_Surface *red_mask =
stk_surface_create( SDL_SWSURFACE, BRICK_WIDTH, BRICK_HEIGHT );
stk_surface_fill( red_mask, 0,0,-1,-1, 0xFF0000 );
SDL_SetAlpha( red_mask, SDL_SRCALPHA, 128 );
SDL_SetColorKey(buffer, 0, 0);
#ifdef AUDIO_ENABLED
stk_sound_play( wav_click );
#endif
SDL_SetEventFilter(0);
event_clear_sdl_queue();
/* backup screen contents */
stk_surface_blit( stk_display, 0,0,-1,-1, buffer, 0,0 );
/* display bricks darkened */
stk_surface_blit( nuke_bkgnd, 0,0,-1,-1,
stk_display, 0,0 );
for ( i = 1; i < MAP_WIDTH - 1; i++ )
for ( j = 1; j < MAP_HEIGHT - 1; j++ )
if ( game->bricks[i][j].id >= 0 )
stk_surface_alpha_blit( brick_pic,
game->bricks[i][j].id * BRICK_WIDTH, 0,
BRICK_WIDTH, BRICK_HEIGHT,
stk_display,
i*BRICK_WIDTH, j*BRICK_HEIGHT, 128 );
/* info */
font->align = STK_FONT_ALIGN_LEFT;
sprintf( buf, _("Plane Of Inner Stability entered (Score: %i)"),
l_paddle->player->stats.total_score + l_paddle->score );
stk_font_write( font, stk_display,
BRICK_WIDTH, (MAP_HEIGHT-1)*BRICK_HEIGHT,
128, buf );
/* show score of player */
stk_display_update( STK_UPDATE_ALL );
x = y = -1;
while (!leave && !stk_quit_request) {
SDL_WaitEvent(&event);
switch ( event.type ) {
case SDL_QUIT:
stk_quit_request = 1;
break;
case SDL_MOUSEBUTTONDOWN:
if ( x != -1 )
if ( confirm( font,
/* xgettext:no-c-format */ _("Disintegrate Brick? (Costs 5% of your score.) y/n"),
CONFIRM_YES_NO ) ) {
/* implant a bomb to this brick and return */
game_set_current( local_game );
brick_start_expl( x,y, BRICK_EXP_TIME,
local_game->paddles[0] );
local_game->bricks[x][y].score = 0;
game_set_current( game );
l_paddle->player->stats.total_score -= (int)(0.05 *
(l_paddle->score +
l_paddle->player->stats.total_score));
leave = 1;
}
break;
case SDL_MOUSEMOTION:
if ( x != -1 ) {
/* clear old selection */
stk_surface_blit( nuke_bkgnd,
x*BRICK_WIDTH, y*BRICK_HEIGHT,
BRICK_WIDTH, BRICK_HEIGHT,
stk_display,
x*BRICK_WIDTH, y*BRICK_HEIGHT );
stk_surface_alpha_blit( brick_pic,
game->bricks[x][y].id * BRICK_WIDTH, 0,
BRICK_WIDTH, BRICK_HEIGHT,
stk_display,
x*BRICK_WIDTH, y*BRICK_HEIGHT, 128 );
stk_display_store_drect();
x = y = -1;
}
/* make new selection if brick */
i = event.motion.x / BRICK_WIDTH;
j = event.motion.y / BRICK_HEIGHT;
if ( i >= 1 && i <= MAP_WIDTH -2 )
if ( j >= 1 && j <= MAP_HEIGHT - 2 )
if ( game->bricks[i][j].id >= 0 ) {
x = i; y = j;
stk_surface_blit( red_mask, 0,0,-1,-1,
stk_display,x*BRICK_WIDTH, y*BRICK_HEIGHT );
stk_display_store_drect();
}
break;
case SDL_KEYDOWN:
if ( event.key.keysym.sym == SDLK_ESCAPE )
leave = 1;
break;
}
stk_display_update( STK_UPDATE_RECTS );
}
stk_surface_blit( buffer, 0,0,-1,-1, stk_display, 0,0 );
stk_display_update( STK_UPDATE_ALL );
SDL_FreeSurface(red_mask);
SDL_FreeSurface(buffer);
SDL_SetEventFilter(event_filter);
}
/* gray screen and display a formatted text, directly update the
* screen */
void display_text( StkFont *font, char *format, ... )
{
int i, y, x;
Text *text;
char buf[512];
va_list args;
va_start( args, format );
vsnprintf( buf, 512, format, args );
va_end( args );
stk_surface_gray( stk_display, 0,0,-1,-1, 2 );
text = create_text( buf, 60 );
font->align = STK_FONT_ALIGN_CENTER_X | STK_FONT_ALIGN_TOP;
y = (stk_display->h - text->count * font->height) / 2;
x = stk_display->w / 2;
for ( i = 0; i < text->count; i++ ) {
stk_font_write(font, stk_display, x, y, STK_OPAQUE, text->lines[i]);
y += font->height;
}
delete_text( text );
stk_display_update( STK_UPDATE_ALL );
}