📄 chart.c
字号:
/*************************************************************************** chart.c - description ------------------- begin : Mon Sep 24 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 "ltris.h"#include "chart.h"#include "list.h"#define CHART_FILE_NAME "ltris.hscr"List *charts = 0; /* list of all loaded level set charts */char chart_path[512]; /* path charts where actually loaded/created from */int chart_loaded = 0; /* true if highscore succesfully loaded */int chart_w, chart_h; /* size of higscore chart */int chart_gap = 10;int chart_level_offset = 0; /* level offset (name's left aligned, score's right aligned) */char *cheader = "Name Level Score";Font *cfont = 0, *chfont = 0, *ccfont = 0; /* normal, highlight and caption font */extern Config config;extern Sdl sdl;extern char *gametype_names[7];/*====================================================================Local====================================================================*//*====================================================================Reset charts====================================================================*/void chart_reset( Set_Chart *chart ){ int i; memset( chart->entries, 0, sizeof( Chart_Entry ) * CHART_ENTRY_COUNT ); for ( i = 0; i < CHART_ENTRY_COUNT; i++ ) chart_add( chart, "............", i + 1, 10000 * ( i + 1 ) ); for ( i = 0; i < CHART_ENTRY_COUNT; i++ ) chart->entries[i].new_entry = 0;}/*====================================================================Create/delete set chart.====================================================================*/Set_Chart* chart_set_create( char *name ){ Set_Chart *chart = calloc( 1, sizeof( Set_Chart ) ); chart->name = strdup( name ); chart_reset( chart ); return chart;}void chart_set_delete( void *ptr ){ Set_Chart *chart = (Set_Chart*)ptr; if ( !chart ) return; if ( chart->name ) free( chart->name ); free( chart );}/*====================================================================Read entries of a chart from file position.====================================================================*/void chart_read_entries( FILE *file, char *file_name, Set_Chart *chart ){ char buffer[128]; int i; for ( i = 0; i < CHART_ENTRY_COUNT; i++ ) { if ( feof( file ) ) { fprintf( stderr, "Unexpected EOF in '%s' in entry %i... reading of highscore aborted.\n", file_name, i ); break; } fgets( buffer, 128, file ); buffer[strlen(buffer) - 1] = 0; /* remove newline */ strcpy( chart->entries[i].name, buffer ); fgets( buffer, 128, file ); buffer[strlen(buffer) - 1] = 0; /* remove newline */ chart->entries[i].level = atoi( buffer ); fgets( buffer, 128, file ); buffer[strlen(buffer) - 1] = 0; /* remove newline */ chart->entries[i].score = strtod( buffer, 0 ); }}/*====================================================================Load all highscores from path. If not found create chart withone set 'Classic'.ReturnValue: True if successful====================================================================*/int chart_load_from_path( char *path ){ FILE *file = 0; char file_name[512]; char setname[1024]; char aux[4]; Set_Chart *chart = 0; /* full file name */ sprintf( file_name, "%s/%s", path, CHART_FILE_NAME ); /* clear chart list */ list_clear( charts ); /* open file */ file = fopen( file_name, "r" ); if ( file ) { /* test if it's new format or old one. */ fread( aux, sizeof( char ), 3, file ); aux[3] = 0; fseek( file, 0, SEEK_SET ); if ( strequal( ">>>", aux ) ) { /* new format: load all set charts */ while( !feof( file ) ) { /* check if next sign is an '>' else skip reading */ aux[0] = 0; fread( aux, sizeof( char ), 1, file ); fseek( file, -1, SEEK_CUR ); if ( aux[0] != '>' ) break; chart = calloc( 1, sizeof( Set_Chart ) ); /* get name: >>>name */ fscanf( file, ">>>%s\n", setname ); chart->name = strdup( setname ); /* entries */ chart_read_entries( file, file_name, chart ); /* add */ list_add( charts, chart ); } } else { /* old format: load single chart as 'Classic' */ fprintf( stderr, "Converting highscore chart as format changed.\n" ); chart = chart_set_create( gametype_names[1] ); chart_read_entries( file, file_name, chart ); list_add( charts, chart ); } fclose( file ); } else { fprintf( stderr, "Highscore chart doesn't exist in '%s'... creating new one.\n", path ); chart = chart_set_create( gametype_names[1] ); list_add( charts, chart ); } /* test if writing is allowed without changing actual contents */ if ( ( file = fopen( file_name, "a" ) ) == 0 ) { fprintf( stderr, "Write permission for '%s' denied.\n", file_name ); return 0; } else fclose( file ); strcpy( chart_path, path ); chart_loaded = 1; return 1;}/*====================================================================Publics====================================================================*//*====================================================================Load highscore. If it doesn't exist try to create it in HI_DIR ifthis fails fall back to ~/.lbreakout and create highscore there.====================================================================*/void chart_load(){ /* create list */ if ( charts ) list_delete( charts ); charts = 0; charts = list_create( LIST_AUTO_DELETE, chart_set_delete ); /* load highscore */ if ( !chart_load_from_path( HI_DIR ) ) { fprintf( stderr, "Unable to access highscore chart in '%s'.\n", HI_DIR ); fprintf( stderr, "Trying to use config directory '%s'.\n", config.dir_name ); if ( !chart_load_from_path( config.dir_name ) ) { fprintf( stderr, "Unable to access highscore chart in config directory... won't be " "able to save any results. Sorry.\n" ); return; } } printf( "Saving highscore chart in: %s\n", chart_path ); /* load resources */ cfont = load_fixed_font( "f_small_yellow.bmp", 32, 96, 8 ); chfont = load_fixed_font( "f_small_white.bmp", 32, 96, 8 ); ccfont = load_fixed_font( "f_yellow.bmp", 32, 96, 10 ); /* compute size and position stuff of highscore */ chart_w = text_width( ccfont, cheader ); chart_h = ccfont->height + chart_gap + /* title + gap */ cfont->height * CHART_ENTRY_COUNT + /* entries */ chart_gap + /*gap between caption and entries */ ccfont->height; /* caption size */ chart_level_offset = text_width( ccfont, "name.-----" ) + text_width( ccfont, "Level" ) / 2; /* level offset centered */}/*====================================================================Delete resources====================================================================*/void chart_delete(){ free_font( &cfont ); free_font( &chfont ); free_font( &ccfont ); if ( charts ) list_delete( charts ); charts = 0;}/*====================================================================Save chart in directory it was loaded from.====================================================================*/void chart_save(){ char file_name[512]; int i; Set_Chart *chart = 0; FILE *file = 0; if ( !chart_loaded ) return; /* full file name */ sprintf( file_name, "%s/%s", chart_path, CHART_FILE_NAME ); /* open file */ file = fopen( file_name, "w" ); if ( !file ) { fprintf( stderr, "??? Highscore chart loaded properly but cannot save?\n" ); return; } /* save all charts */ list_reset( charts ); while ( ( chart = list_next( charts ) ) != 0 ) { fprintf( file, ">>>%s\n", chart->name ); for ( i = 0; i < CHART_ENTRY_COUNT; i++ ) fprintf( file, "%s\n%i\n%.0f\n", chart->entries[i].name, chart->entries[i].level, chart->entries[i].score ); } fclose( file );}/*====================================================================Check if this player entered the highscore chart and update it.====================================================================*/void chart_add( Set_Chart *chart, char *name, int level, double score ){ /* add new entry at blind end of chart */ strcpy( chart->entries[CHART_ENTRY_COUNT].name, name ); chart->entries[CHART_ENTRY_COUNT].level = level; chart->entries[CHART_ENTRY_COUNT].score = score; chart->entries[CHART_ENTRY_COUNT].new_entry = 1; /* sort algorithm is stable so first sort levels then score */ chart_sort( chart, SORT_BY_LEVEL ); chart_sort( chart, SORT_BY_SCORE );}/*====================================================================Sort chart with stable algorithm (bubble sort's ok) by wantedvalue.====================================================================*/void chart_swap( Chart_Entry *entry1, Chart_Entry *entry2 ){ Chart_Entry dummy; dummy = *entry1; *entry1 = *entry2; *entry2 = dummy;}void chart_sort( Set_Chart *chart, int type ){ int j; int changed = 0; /* use entry dummy as well so count is CHART_ENTRY_COUNT + 1 */ do { changed = 0; for ( j = 0; j < CHART_ENTRY_COUNT; j++ ) switch ( type ) { case SORT_BY_LEVEL: if ( chart->entries[j].level < chart->entries[j + 1].level ) { chart_swap( &chart->entries[j], &chart->entries[j + 1] ); changed = 1; } break; case SORT_BY_SCORE: if ( chart->entries[j].score < chart->entries[j + 1].score ) { chart_swap( &chart->entries[j], &chart->entries[j + 1] ); changed = 1; } break; } } while ( changed );}/*====================================================================Draw highscores centered in regio x,y,w,h====================================================================*/void chart_show( Set_Chart *chart, int x, int y, int w, int h ){ char number_buffer[24]; int entry_offset; /* y offset of entries */ Font *font; int i; /* adjust x,y so it's centered */ x += ( w - chart_w ) / 2; y += ( h - chart_h ) / 2; /* title = name of levelset */ ccfont->align = ALIGN_X_CENTER | ALIGN_Y_TOP; write_text( ccfont, sdl.screen, x + ( chart_w >> 1 ), y, chart->name, OPAQUE ); /* caption */ ccfont->align = ALIGN_X_LEFT | ALIGN_Y_TOP; write_text( ccfont, sdl.screen, x, y + ccfont->height + chart_gap, cheader, OPAQUE ); /* get entry offset */ entry_offset = ( ccfont->height + chart_gap ) * 2 + y; /* entries */ for ( i = 0; i < CHART_ENTRY_COUNT; i++ ) { font = cfont; if ( chart->entries[i].new_entry ) font = chfont; /* name */ font->align = ALIGN_X_LEFT | ALIGN_Y_TOP; write_text( font, sdl.screen, x, entry_offset, chart->entries[i].name, OPAQUE ); /* level */ font->align = ALIGN_X_CENTER | ALIGN_Y_TOP; sprintf( number_buffer, "%i", chart->entries[i].level ); write_text( font, sdl.screen, x + chart_level_offset, entry_offset, number_buffer, OPAQUE ); /* score */ font->align = ALIGN_X_RIGHT | ALIGN_Y_TOP; sprintf( number_buffer, "%.0f", chart->entries[i].score ); write_text( font, sdl.screen, x + chart_w, entry_offset, number_buffer, OPAQUE ); /* change offset */ entry_offset += font->height; } add_refresh_rect( x, y, chart_w, chart_h );}/*====================================================================Clear all new_entry flags (done before new players are addedto chart when game over).====================================================================*/void chart_clear_new_entries(){ int i; Set_Chart *chart; list_reset( charts ); while ( ( chart = list_next( charts ) ) != 0 ) { chart->entries[CHART_ENTRY_COUNT].score = chart->entries[CHART_ENTRY_COUNT].level = 0; for ( i = 0; i < CHART_ENTRY_COUNT + 1; i++ ) chart->entries[i].new_entry = 0; }}/*====================================================================Query set chart by this name or if not found create a new oneby this name.====================================================================*/Set_Chart* chart_set_query( char *name ){ Set_Chart *chart = 0; list_reset( charts ); while ( ( chart = list_next( charts ) ) != 0 ) if ( strequal( name, chart->name ) ) return chart; /* not found so create it */ fprintf( stderr, "First chart query for '%s'. Creating this chart.\n", name ); chart = chart_set_create( name ); list_add( charts, chart ); return chart;}/*====================================================================Query chart by id. If id is invalid return 0.====================================================================*/Set_Chart* chart_set_query_id( int id ){ if ( id >= charts->count ) { fprintf( stderr, "Chart index '%i' is out of range!\n", id ); return 0; } return (Set_Chart*)list_get( charts, id );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -