/* save data from local and local_game variables and update * the menu hint. */ void save_local_game( int slot_id ) { GameSlot gs; int i; memset( &gs, 0, sizeof(GameSlot) ); strcpy( gs.setname, game_set->name ); gs.diff = config.diff; gs.player_count = config.player_count; gs.cur_player = current_player; for ( i = 0; i < MAX_PLAYERS; i++ ) { strcpy( gs.player_names[i], config.player_names[i] ); gs.player_cur_level_id[i] = players[i].level_id; gs.player_lives[i] = players[i].lives; gs.player_scores[i] = players[i].stats.total_score; } gs.gameSeed = gameSeed; if ( !slot_save( slot_id, &gs ) ) fprintf( stderr, "ERROR: couldn't save game!\n" ); slot_update_hint( slot_id, item_resume_0->hint ); }
/* ==================================================================== Load/delete background and create and link all menus ==================================================================== */ void manager_create() { int i, j; Item *keys[7]; Item *item; int filter[SDLK_LAST]; /* key filter */ /* constant contence of switches */ char *str_fps[] = { _("No Limit"), _("100 FPS") }; char *str_anim[] = { _("Off"), _("Low"), _("Medium"), _("High") }; char *str_diff[] = { _("Kids"), _("Easy"), _("Medium"), _("Hard") }; /* main: new game: start game quick help --- levelset difficulty --- active players --- player1 player2 player3 player4 controls graphics animations transparency shadow --- display constant frame rate audio: sound volume advanced options: convex paddle ball level key speed editor: set: (list) edit delete yes no --- create empty set set name: (string) create set yes no --- quit */ Menu *_main = 0; #ifdef _1 Menu *options = 0; #endif #ifdef AUDIO_ENABLED Menu *audio = 0; #endif Menu *gfx = 0; Menu *game = 0; Menu *cont = 0; Menu *adv = 0; Menu *editor = 0; Menu *confirm_delete = 0; Menu *theme = 0; /* load levelset names */ levelsets_load_names(); cb_update_edit_set(); /* hints will be displayed on menu background */ hint_set_bkgnd( mbkgnd ); /* setup filter */ filter_clear( filter ); filter_set( filter, SDLK_a, SDLK_z, 1 ); filter[SDLK_BACKSPACE] = 1; filter[SDLK_SPACE] = 1; filter[SDLK_RSHIFT] = 1; filter[SDLK_LSHIFT] = 1; filter[SDLK_LALT] = 1; filter[SDLK_RALT] = 1; filter[SDLK_LCTRL] = 1; filter[SDLK_RCTRL] = 1; filter[SDLK_UP] = 1; filter[SDLK_DOWN] = 1; filter[SDLK_LEFT] = 1; filter[SDLK_RIGHT] = 1; filter[SDLK_q] = 0; filter[SDLK_p] = 0; filter[SDLK_f] = 0; filter[SDLK_s] = 0; filter[SDLK_a] = 0; filter[SDLK_r] = 0; filter[SDLK_h] = 0; filter[SDLK_d] = 0; /* menus are added to this list for deleting later */ menus = list_create( LIST_AUTO_DELETE, menu_delete ); /* create menus */ _main = menu_create( _("Menu"), MENU_LAYOUT_CENTERED, menu_x, menu_y, menu_w, menu_h, menu_border, 1 ); #ifdef _1 options = menu_create( _("Options"), MENU_LAYOUT_CENTERED, menu_x, menu_y, menu_w, menu_h, menu_border, 1 ); #endif gfx = menu_create( _("Graphics"), MENU_LAYOUT_CENTERED, menu_x, menu_y, menu_w, menu_h, menu_border, 1 ); game = menu_create( _("Local Game"), MENU_LAYOUT_CENTERED, menu_x, menu_y, menu_w, menu_h, menu_border, 1 ); cont = menu_create( _("Controls"), MENU_LAYOUT_CENTERED, menu_x, menu_y, menu_w, menu_h, menu_border, 1 ); adv = menu_create( _("Advanced Options"), MENU_LAYOUT_CENTERED, menu_x, menu_y, menu_w, menu_h, menu_border, 1 ); #ifdef AUDIO_ENABLED audio = menu_create( _("Audio"), MENU_LAYOUT_CENTERED, menu_x, menu_y, menu_w, menu_h, menu_border, 1 ); #endif editor = menu_create( _("Editor"), MENU_LAYOUT_CENTERED, menu_x, menu_y, menu_w, menu_h, menu_border, 1 ); confirm_delete = menu_create( _("Delete Set"), MENU_LAYOUT_CENTERED, menu_x, menu_y, menu_w, menu_h, menu_border, 1 ); theme = menu_create( _("Select Theme"), MENU_LAYOUT_CENTERED, menu_x, menu_y, menu_w, menu_h, menu_border, 1 ); /* create items */ /* main menu */ menu_add( _main, item_create_link ( _("Local Game"), HINT_LOCAL, game ) ); #ifdef NETWORK_ENABLED menu_add( _main, item_create_action ( _("Network Game"), HINT_NETWORK, ACTION_CLIENT ) ); #endif menu_add( _main, item_create_action ( _("Quick Help"), HINT_, ACTION_QUICK_HELP ) ); // menu_add( _main, item_create_link ( _("Select Theme"), HINT_THEME, theme ) ); menu_add( _main, item_create_separator ( "" ) ); #ifdef _1 menu_add( _main, item_create_link ( _("Options"), options ) ); #endif menu_add( _main, item_create_link ( _("Controls"), HINT_, cont ) ); menu_add( _main, item_create_link ( _("Graphics"), HINT_, gfx ) ); #ifdef AUDIO_ENABLED menu_add( _main, item_create_link ( _("Audio"), HINT_,audio ) ); #else menu_add( _main, item_create_separator ( _("Audio") ) ); #endif menu_add( _main, item_create_link ( _("Advanced Options"), HINT_, adv ) ); menu_add( _main, item_create_separator ( "" ) ); menu_add( _main, item_create_link ( _("Editor"), HINT_, editor ) ); menu_add( _main, item_create_separator ( "" ) ); menu_add( _main, item_create_action ( _("Quit"), HINT_QUIT, ACTION_QUIT ) ); #ifdef _1 /* options */ menu_add( options, item_create_link( _("Controls"), HINT_, cont ) ); menu_add( options, item_create_link( _("Graphics"), HINT_, gfx ) ); menu_add( options, item_create_link( _("Audio"), HINT_, audio ) ); menu_add( options, item_create_separator( _("Audio") ) ); menu_add( options, item_create_separator( "" ) ); menu_add( options, item_create_link( _("Back"), _main ) ); #endif /* audio */ #ifdef AUDIO_ENABLED item = item_create_switch( _("Sound:"), HINT_, &config.sound, _("Off"), _("On") ); item->callback = cb_sound; menu_add( audio, item ); menu_add( audio, item_create_switch( _("Speech:"), HINT_, &config.speech, _("Off"), _("On") ) ); item = item_create_range( _("Volume:"), HINT_, &config.volume, 1, 8, 1 ); item->callback = cb_volume; menu_add( audio, item ); menu_add( audio, item_create_separator( "" ) ); menu_add( audio, item_create_link( _("Back"), HINT_, _main ) ); #endif /* gfx */ menu_add( gfx, item_create_switch_x( _("Animations:"), HINT_ANIM, &config.anim, str_anim, 4 ) ); menu_add( gfx, item_create_switch( _("Bonus Info:"), HINT_BONUS_INFO, &config.bonus_info, _("Off"), _("On") ) ); menu_add( gfx, item_create_separator( "" ) ); item = item_create_switch( _("Display:"), HINT_DISPLAY, &config.fullscreen, _("Window"), _("Fullscreen") ); item->callback = cb_fullscreen; menu_add( gfx, item ); menu_add( gfx, item_create_switch_x( _("Frame Rate:"), HINT_FPS, &config.fps, str_fps, 2 ) ); menu_add( gfx, item_create_separator( "" ) ); menu_add( gfx, item_create_link( _("Select Theme"), HINT_THEME, theme ) ); menu_add( gfx, item_create_separator( "" ) ); menu_add( gfx, item_create_link( _("Back"), HINT_, _main ) ); /* game */ item_resume_0 = item_create_action( _("Resume Last Game"), "???", ACTION_RESUME_0 ); menu_add( game, item_resume_0 ); slot_update_hint( 0, item_resume_0->hint ); menu_add( game, item_create_action( _("Start Original Set"), HINT_START_LBR, ACTION_PLAY_LBR ) ); menu_add( game, item_create_action( _("Start AddOn"), HINT_START_CUSTOM, ACTION_PLAY_CUSTOM ) ); //menu_add( game, item_create_separator( "" ) ); item_levelset = item_create_switch_x( _("AddOn:"), "", &config.levelset_id_local, levelset_names_local, levelset_count_local ); item_levelset->callback = cb_update_levelset_hint; cb_update_levelset_hint(); /* initiate first hint */ menu_add( game, item_levelset ); menu_add( game, item_create_switch_x( _("Difficulty:"), HINT_DIFF, &config.diff, str_diff, DIFF_COUNT ) ); menu_add( game, item_create_separator( "" ) ); menu_add( game, item_create_range( _("Players:"), HINT_PLAYERS, &config.player_count, 1, 4, 1 ) ); menu_add( game, item_create_edit( _("1st:"), HINT_PLAYERS, config.player_names[0], 12 ) ); menu_add( game, item_create_edit( _("2nd:"), HINT_PLAYERS, config.player_names[1], 12 ) ); menu_add( game, item_create_edit( _("3rd:"), HINT_PLAYERS, config.player_names[2], 12 ) ); menu_add( game, item_create_edit( _("4th:"), HINT_PLAYERS, config.player_names[3], 12 ) ); menu_add( game, item_create_separator( "" ) ); menu_add( game, item_create_link( _("Back"), HINT_, _main ) ); /* controls */ keys[0] = item_create_key( _("Left:"), HINT_KEYS, &config.k_left, filter ); keys[1] = item_create_key( _("Right:"), HINT_KEYS, &config.k_right, filter ); keys[2] = item_create_key( _("Left Fire:"), HINT_KEYS, &config.k_lfire, filter ); keys[3] = item_create_key( _("Right Fire:"), HINT_KEYS, &config.k_rfire, filter ); keys[4] = item_create_key( _("Paddle Turbo:"), HINT_KEYS, &config.k_turbo, filter ); keys[5] = item_create_key( _("Ball Turbo:"), HINT_KEYS, &config.k_maxballspeed, filter ); keys[6] = item_create_key( _("Return:"), HINT_KEYS, &config.k_return, filter ); // keys[6] = item_create_key( _("Warp:"), HINT_KEYS, &config.k_warp, filter ); for ( i = 0; i < 7; i++ ) menu_add( cont, keys[i] ); /* dynamic restriction */ for ( i = 0; i < 7; i++ ) for ( j = 0; j < 7; j++ ) if ( j != i ) value_add_other_key( keys[i]->value, keys[j]->value ); /* other control stuff */ menu_add( cont, item_create_separator( "" ) ); item = item_create_range( _("Key Speed:"), HINT_KEYSPEED, &config.i_key_speed, 100, 1000, 50 ); item->callback = cb_set_keyspeed; menu_add( cont, item ); item = item_create_range( _("Motion Modifier:"), HINT_MOD, &config.i_motion_mod, 40, 160, 5 ); item->callback = cb_set_motion_mod; menu_add( cont, item ); menu_add( cont, item_create_switch( _("Invert Motion:"), HINT_INVERT, &config.invert, _("Off"), _("On") ) ); menu_add( cont, item_create_separator( "" ) ); menu_add( cont, item_create_link( _("Back"), HINT_, _main ) ); /* advanced options */ menu_add( adv, item_create_switch( _("Convex Paddle:"), HINT_CONVEX, &config.convex, _("Off"), _("On") ) ); //menu_add( adv, item_create_switch( _("Corner:"), HINT_CORNER, &config.linear_corner, _("Spherical"), _("Linear") ) ); menu_add( adv, item_create_switch( _("Ball Fire Angle:"), HINT_RANDOM_ANGLE, &config.random_angle, "50", _("Random") ) ); menu_add( adv, item_create_switch( _("Balls:"), HINT_BALLLEVEL, &config.ball_level, _("Below Bonuses"), _("Above Bonuses") ) ); menu_add( adv, item_create_switch( _("Debris:"), HINT_DEBRISLEVEL, &config.debris_level, _("Below Balls"), _("Above Balls") ) ); menu_add( adv, item_create_switch( _("Return Balls:"), HINT_RETURN, &config.return_on_click, _("Auto"), _("By Click") ) ); item = item_create_switch( _("Use Hints:"), HINT_USEHINTS, &config.use_hints, _("Off"), _("On") ); item->callback = cb_hints; menu_add( adv, item ); menu_add( adv, item_create_range( _("Warp Limit:"), HINT_WARP_LIMIT, &config.rel_warp_limit, 0, 100, 10 ) ); menu_add( adv, item_create_edit( _("Local UDP Port:"), HINT_LOCAL_PORT, config.local_port, 6 ) ); item = item_create_range( _("Acc. Ball Speed:"), HINT_MAXBALLSPEED, &config.maxballspeed_int1000, 600, 900, 20 ); item->callback = cb_maxballspeed; menu_add( adv, item ); menu_add( adv, item_create_switch( _("Add Bonus Levels:"), HINT_BONUS_LEVELS, &config.addBonusLevels, _("Off"), _("On") ) ); menu_add( adv, item_create_separator( "" ) ); menu_add( adv, item_create_link( _("Back"), HINT_, _main ) ); /* editor */ item_set = item_create_switch_x( _("Set:"), HINT_EDITOR_SET, &config.levelset_id_home, levelset_names_home, levelset_count_home ); item_set->callback = cb_update_edit_set; menu_add( editor, item_set ); menu_add( editor, item_create_action( _("Edit Set"), HINT_EDITOR_EDIT, ACTION_EDIT ) ); menu_add( editor, item_create_link( _("Delete Set"), HINT_EDITOR_DELETE, confirm_delete ) ); menu_add( editor, item_create_separator( "" ) ); menu_add( editor, item_create_link( _("Back"), HINT_, _main ) ); /* confirm_delete set */ item = item_create_link( _("Yes"), HINT_ ,editor ); item->callback = cb_delete_set; menu_add( confirm_delete, item ); menu_add( confirm_delete, item_create_link( _("No"), HINT_, editor ) ); /* theme */ item_theme = item_create_switch_x( _("Theme:"), "", &config.theme_id, theme_names, theme_count ); menu_add( theme, item_theme ); item_theme->callback = cb_update_theme_hint; cb_update_theme_hint(); menu_add( theme, item_create_separator( "" ) ); item = item_create_link( _("Apply"), HINT_APPLY, gfx ); item->callback = cb_change_theme; menu_add( theme, item ); menu_add( theme, item_create_link( _("Cancel"), HINT_, gfx ) ); /* adjust all menus */ menu_adjust( _main ); #ifdef _1 menu_adjust( options ); #endif #ifdef AUDIO_ENABLED menu_adjust( audio ); #endif menu_adjust( gfx ); menu_adjust( game ); menu_adjust( cont ); menu_adjust( adv ); menu_adjust( editor ); menu_adjust( confirm_delete ); menu_adjust( theme ); /* set main menu as current */ menu_select( _main ); }
/* run the state driven loop until game is broken up or finished */ void client_game_run( void ) { int ms, frame_delay = config.fps?10:1; int button_clicked, key_pressed; SDL_Event event; int abort = 0, i, j, penalty; /* frame rate */ int frames = 0; int frame_time = SDL_GetTicks(); event_clear_sdl_queue(); stk_display_fade( STK_FADE_IN, STK_FADE_DEFAULT_TIME ); stats_received = 0; stk_timer_reset(); ms = 1; while ( !abort && !stk_quit_request ) { /* check wether an event occured */ button_clicked = key_pressed = 0; if ( SDL_PollEvent( &event ) ) { if ( client_state == CS_PAUSE && game->game_type == GT_NETWORK ) gui_dispatch_event( &event, ms ); else if ( event.type == SDL_MOUSEBUTTONDOWN ) button_clicked = event.button.button; else if ( event.type == SDL_KEYDOWN ) { key_pressed = event.key.keysym.sym; if ( handle_default_key( key_pressed, &abort ) ) key_pressed = 0; } else if (event.type == SDL_ACTIVEEVENT) { if (event.active.state == SDL_APPINPUTFOCUS || event.active.state == SDL_APPACTIVE ) if (event.active.gain == 0 ) client_set_pause(1); } } else if ( client_state == CS_PAUSE && game->game_type == GT_NETWORK ) gui_dispatch_event( 0, ms ); /* check whether Shift is pressed to switch between own and highest score */ if (game->game_type == GT_LOCAL) handle_display_switch(); /* let server know we're still alive except * in CS_PLAY as we send paddle updates there */ if ( game->game_type == GT_NETWORK ) comm_send_heartbeat(); /* handle client */ switch ( client_state ) { case CS_FINAL_STATS: if ( key_pressed==SDLK_SPACE ) abort = 1; break; case CS_FATAL_ERROR: /* after game was violently broken up the server * may still send the stats of the game so far */ if ( button_clicked || key_pressed ) { SDL_Delay(250); /* give time to release button */ set_state( CS_RECV_STATS ); display_text( font, "Receiving final stats..." ); } break; case CS_FINAL_TABLE: if ( button_clicked || key_pressed ) { check_highscores(); select_chart( game_set->name, 0 ); /* remove saved game */ slot_delete( 0 ); slot_update_hint( 0, item_resume_0->hint ); /* quit local game */ abort = 1; } break; case CS_SCORE_TABLE: /* show who's next player and scores in local game */ display_score_table( "Next Player: %s", cur_player->name ); set_state( CS_GET_READY ); break; case CS_BONUS_LEVEL_SCORE: /* display total score from this level for player */ display_bonus_level_score(); set_state( CS_GET_READY_FOR_NEXT_LEVEL ); break; case CS_FINAL_PLAYER_INFO: if ( button_clicked || key_pressed ) { SDL_Delay(250); /* give time to release button */ set_state( CS_NEXT_PLAYER ); } break; case CS_RECV_LEVEL: comm_recv(); if ( cur_player->next_level_received ) { cur_player->next_level_received = 0; cur_player->paddle_id = cur_player->next_paddle_id; init_next_round(); } break; case CS_RECV_STATS: comm_recv(); if ( stats_received ) { set_state( CS_FINAL_STATS ); display_final_stats(); } break; case CS_ROUND_RESULT: if ( button_clicked || key_pressed ) { SDL_Delay(250); /* give time to release button */ if ( game_over ) { set_state( CS_RECV_STATS ); display_text( font, "Receiving final stats..." ); } else { set_state( CS_RECV_LEVEL ); display_text( font, "Receiving level data..." ); } } break; case CS_GET_READY: if ( button_clicked || key_pressed ) { SDL_Delay(250); /* give time to release button */ comm_send_short( MSG_READY ); set_state( CS_PLAY ); } break; case CS_GET_READY_FOR_NEXT_LEVEL: if ( button_clicked || key_pressed ) { SDL_Delay(250); /* give time to release button */ set_state( CS_NEXT_LEVEL ); } break; case CS_PAUSE: if ( game->game_type == GT_LOCAL ) break; /* check wether pause chatroom has been closed * either by client or remote */ comm_recv(); break; case CS_PLAY: /* hide objects */ begin_frame(); /* apply events to local paddle */ paddle_handle_events( l_paddle, ms ); /* update local objects and communicate if * comm_delay ms have passed */ update_game( ms ); /* show objects */ end_frame(); /* handle local level over */ if ( game->level_over ) { if ( game->game_type == GT_LOCAL ) { if ( game_set == 0 ) { abort = 1; /* was a test level */ grab_input(0); break; } if ( game->winner == PADDLE_BOTTOM ) { if (local_game->isBonusLevel) set_state( CS_BONUS_LEVEL_SCORE ); else set_state( CS_NEXT_LEVEL ); } else set_state( CS_LOOSE_LIFE ); } else { finalize_round(); } } break; case CS_NEXT_LEVEL: /* apply paddle stats to player */ game_set_current( local_game ); game_update_stats( PADDLE_BOTTOM, &cur_player->stats ); game_set_current( game ); /* init next level for player in local game */ cur_player->level_id++; if ( cur_player->level_id >= game_set->count ) { /* deactivate player */ cur_player->lives = 0; display_text( font, "You've cleared all levels...#Congratulations!!!" ); set_state( CS_FINAL_PLAYER_INFO ); break; } /* get snapshot for next init */ cur_player->snapshot = *game_set->levels[cur_player->level_id]; /* cycle players */ set_state( CS_NEXT_PLAYER ); break; case CS_RESTART_LEVEL: /* apply paddle stats to player */ game_set_current( local_game ); game_update_stats( PADDLE_BOTTOM, &cur_player->stats ); game_set_current( game ); /* reset level for next turn */ cur_player->snapshot = *game_set->levels[cur_player->level_id]; /* decrease lives (is checked that this wasn't the last one) */ cur_player->lives--; /* cycle players */ set_state( CS_NEXT_PLAYER ); break; case CS_LOOSE_LIFE: /* apply paddle stats to player */ game_set_current( local_game ); game_update_stats( PADDLE_BOTTOM, &cur_player->stats ); game_set_current( game ); /* remember level for next turn */ game_get_level_snapshot( &cur_player->snapshot ); /* decrease lives */ cur_player->lives--; if ( cur_player->lives == 0 ) { display_text( font, "You've lost all lives...#Do you want to buy a continue#for 100%% of your score? y/n" ); set_state( CS_CONFIRM_CONTINUE ); //set_state( CS_FINAL_PLAYER_INFO ); break; } set_state( CS_NEXT_PLAYER ); break; case CS_NEXT_PLAYER: /* game over? */ if ( players_count() == 0 ) { display_score_table( "Game Over!" ); set_state( CS_FINAL_TABLE ); break; } /* speak and fade */ play_speech(); fade_anims(); /* finalize current game context */ finalize_level(); /* set next player */ cur_player = players_get_next(); init_level( cur_player, PADDLE_BOTTOM ); if ( player_count > 1 ) set_state( CS_SCORE_TABLE ); else { set_state( CS_PLAY ); /* one player starts immediately */ stk_display_update( STK_UPDATE_ALL ); } break; case CS_CONFIRM_CONTINUE: case CS_CONFIRM_QUIT: case CS_CONFIRM_WARP: case CS_CONFIRM_RESTART: if ( key_pressed == 0 ) break; if ( key_pressed==SDLK_n||key_pressed==SDLK_ESCAPE ) { /* if denying continue... DIE!!! */ if ( client_state == CS_CONFIRM_CONTINUE ) { SDL_Delay(250); /* give time to release button */ set_state( CS_NEXT_PLAYER ); //set_state( CS_FINAL_PLAYER_INFO ); } else set_state( CS_PLAY ); break; } if ( key_pressed != SDLK_y && key_pressed != SDLK_z ) break; /* handle confirmed action */ SDL_Delay(250); /* give time to release button */ switch( client_state ) { case CS_CONFIRM_CONTINUE: /* clear score and give full lives again */ cur_player->lives = game->diff->lives; cur_player->stats.total_score = 0; set_state( CS_NEXT_PLAYER ); break; case CS_CONFIRM_QUIT: comm_send_short( MSG_QUIT_GAME ); if ( game->game_type == GT_LOCAL ) { /* apply paddle stats to player */ game_set_current( local_game ); game_update_stats( PADDLE_BOTTOM, &cur_player->stats ); game_set_current( game ); /* no higscore check anymore as game is supposed to * be resumed until normal game over */ /* testing levels don't got for * high scores *** if ( game_set ) { check_highscores(); select_chart( game_set->name, 0 ); }*/ /* save local game */ if ( game_set != 0 /*not testing a level*/ ) save_local_game( 0 ); abort = 1; } else { /* await game stats */ set_state( CS_RECV_STATS ); display_text( font, "Receiving final stats..." ); } break; case CS_CONFIRM_WARP: game->winner = -1; /* no speech */ local_game->winner = -1; /* not counted as win */ /* substract doubled score of remaining bricks */ penalty = 0; for ( i = 0; i < MAP_WIDTH; i++ ) for ( j = 0; j < MAP_HEIGHT; j++ ) if ( local_game->bricks[i][j].dur != -1 ) penalty += local_game->bricks[i][j].score; printf( "warp penalty: -%d\n", penalty ); local_game->paddles[0]->score -= penalty; set_state( CS_NEXT_LEVEL ); break; case CS_CONFIRM_RESTART: game->winner = -1; /* no speech */ local_game->winner = -1; /* not counted as win */ local_game->level_over = 1; set_state( CS_RESTART_LEVEL ); break; } break; } /* update anything that was changed */ stk_display_update( STK_UPDATE_RECTS ); /* get time since last call and delay if below frame_delay */ ms = stk_timer_get_time(); if ( ms < frame_delay ) { SDL_Delay( frame_delay - ms ); ms += stk_timer_get_time(); } frames++; } finalize_level(); client_state = CLIENT_NONE; stk_display_fade( STK_FADE_OUT, STK_FADE_DEFAULT_TIME ); if ( stk_quit_request ) comm_send_short( MSG_DISCONNECT ); else comm_send_short( MSG_UNHIDE ); /* frame rate */ frame_time = SDL_GetTicks() - frame_time; printf( "Time: %.2f, Frames: %i -> FPS: %.2f\n", (double)frame_time / 1000, frames, 1000.0*frames/frame_time ); event_clear_sdl_queue(); /* update the selected user and the user list in network as * we received ADD/REMOVE_USER messages */ gui_list_update( list_users, client_users->count ); /* re-select current entry */ if ( client_user ) { i = list_check( client_users, client_user ); if ( i != -1 ) gui_list_select( list_users, 0, i, 1 ); } }