Add module 'files'
- write score after death - read a number of scores
This commit is contained in:
		
							parent
							
								
									7acb37824e
								
							
						
					
					
						commit
						b5e85de24c
					
				@ -53,6 +53,7 @@ set(SOURCES
 | 
			
		||||
    src/common.c
 | 
			
		||||
    src/sound.c
 | 
			
		||||
    src/difficulty.c
 | 
			
		||||
    src/files.c
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								include/files.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								include/files.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#define MAX_PRINTED_SCORES  5
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// struct that store player score at the end of the game
 | 
			
		||||
typedef struct playerScore_t
 | 
			
		||||
{
 | 
			
		||||
    int score;
 | 
			
		||||
    char playerName[30];
 | 
			
		||||
    int difficulty;
 | 
			
		||||
    char map[30];
 | 
			
		||||
} playerScore_t;
 | 
			
		||||
 | 
			
		||||
// global struct for storing the 10 best players after reading it from the file (defined in files.c)
 | 
			
		||||
extern playerScore_t topScores[MAX_PRINTED_SCORES];
 | 
			
		||||
 | 
			
		||||
// function which saves score in a .bin file
 | 
			
		||||
void savePlayerScore(const char *filename);
 | 
			
		||||
 | 
			
		||||
// function which reads the 10 best finisher from the .bin file
 | 
			
		||||
void readTopScores(const char *filename);
 | 
			
		||||
 | 
			
		||||
// counts records in file
 | 
			
		||||
int countRecordsInFile(const char *filename); 
 | 
			
		||||
@ -33,19 +33,14 @@ typedef struct gameData_t
 | 
			
		||||
} gameData_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// struct that store player score at the end of the game
 | 
			
		||||
typedef struct playerScore_t
 | 
			
		||||
{
 | 
			
		||||
    int score;
 | 
			
		||||
    char playerName[30];
 | 
			
		||||
    int difficulty;
 | 
			
		||||
    char map[30];
 | 
			
		||||
} playerScore_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// global struct for storing all game data (defined in game.c)
 | 
			
		||||
extern gameData_t game;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// run once at game start and does the following:
 | 
			
		||||
// - init snake
 | 
			
		||||
// - load map
 | 
			
		||||
@ -63,5 +58,3 @@ void handlePortals(); //(ran in gameCycle)
 | 
			
		||||
// - triggers frame update (render.c)
 | 
			
		||||
void runGameCycle();
 | 
			
		||||
 | 
			
		||||
// function which saves score in a .csv file
 | 
			
		||||
  // void savePlayerScore()
 | 
			
		||||
							
								
								
									
										147
									
								
								src/files.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								src/files.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,147 @@
 | 
			
		||||
#include "game.h"
 | 
			
		||||
#include "menu.h"
 | 
			
		||||
#include "files.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//global struct for storing all data of the 10 best players
 | 
			
		||||
playerScore_t topScores[];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//==========================
 | 
			
		||||
//==== savePlayerScores ====
 | 
			
		||||
//==========================
 | 
			
		||||
 void savePlayerScore(const char *filename/*int score, int difficulty, const char *playerName,  const char *map*/) 
 | 
			
		||||
 {   
 | 
			
		||||
    playerScore_t playerScore;
 | 
			
		||||
 | 
			
		||||
    // copy data into struct
 | 
			
		||||
    playerScore.score = game.snake.length - config.snakeDefaultLength;
 | 
			
		||||
    playerScore.difficulty = config.difficulty;
 | 
			
		||||
    strcpy(playerScore.playerName, ttlStorage.userName);
 | 
			
		||||
    strcpy(playerScore.map, "testmap");
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    FILE *file;
 | 
			
		||||
    // open file
 | 
			
		||||
    file = fopen(filename, "ab");
 | 
			
		||||
 | 
			
		||||
    // write data in file
 | 
			
		||||
    if (file != NULL) 
 | 
			
		||||
    {
 | 
			
		||||
        fwrite(&playerScore, sizeof(playerScore_t), 1, file);
 | 
			
		||||
        fclose(file);
 | 
			
		||||
 | 
			
		||||
        LOGI("Spielergebnis wurde erfolgreich in die Binaerdatei gespeichert.\n");
 | 
			
		||||
    } 
 | 
			
		||||
    else 
 | 
			
		||||
    {
 | 
			
		||||
        LOGI("Fehler beim Öffnen der Datei!\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//==========================
 | 
			
		||||
//==== readTopScores ======
 | 
			
		||||
//==========================
 | 
			
		||||
// number of reads depends on  'MAX_PRINTED_SCORES'
 | 
			
		||||
void readTopScores(const char *filename)
 | 
			
		||||
{
 | 
			
		||||
    FILE *filePtr;
 | 
			
		||||
    playerScore_t tempPlayerScore;
 | 
			
		||||
    int recordsInFile;
 | 
			
		||||
    int highestPlayerScore;
 | 
			
		||||
    int count = 0;              // increase up to 'MAX_PRINTED_SCORES'
 | 
			
		||||
 | 
			
		||||
    // determine the number of contents in the file
 | 
			
		||||
    recordsInFile = countRecordsInFile(filename);
 | 
			
		||||
    // if failure
 | 
			
		||||
    if(recordsInFile == -1)
 | 
			
		||||
    {
 | 
			
		||||
        game.gameState = EXIT;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    filePtr = fopen(filename, "rb");
 | 
			
		||||
 | 
			
		||||
    // fail with file opening
 | 
			
		||||
    if (filePtr == NULL) 
 | 
			
		||||
    {
 | 
			
		||||
        LOGI("Datei:  Fehler beim Öffnen der Datei für die besten 10 Ergebnisse!\n");
 | 
			
		||||
        game.gameState = EXIT;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    LOGI("Datensaetze in Datei: %d\n", recordsInFile);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //---- search for the highest score------
 | 
			
		||||
    for (int i = 0; i < recordsInFile; i++) 
 | 
			
		||||
    {
 | 
			
		||||
        fread(&tempPlayerScore, sizeof(playerScore_t), 1, filePtr);
 | 
			
		||||
        if(tempPlayerScore.score > highestPlayerScore)
 | 
			
		||||
        {
 | 
			
		||||
            highestPlayerScore == tempPlayerScore.score;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    //--- decrease highest score -----
 | 
			
		||||
    while((count < MAX_PRINTED_SCORES) && (count < MAX_PRINTED_SCORES))
 | 
			
		||||
    {   
 | 
			
		||||
        // set file pointer to start of the file
 | 
			
		||||
        rewind(filePtr);    
 | 
			
		||||
 | 
			
		||||
        // search for the highest score and then save it in topScores
 | 
			
		||||
        for (int i = 0; i < recordsInFile; i++) 
 | 
			
		||||
        {   
 | 
			
		||||
            fread(&tempPlayerScore, sizeof(playerScore_t), 1, filePtr);
 | 
			
		||||
 | 
			
		||||
            // current highscore found
 | 
			
		||||
            if(tempPlayerScore.score == highestPlayerScore)    
 | 
			
		||||
            {
 | 
			
		||||
                topScores[count] = tempPlayerScore;
 | 
			
		||||
                LOGI("score: %d  name: %s  schwierigkeit: %d  map: %s\n", topScores[count].score, topScores[count].playerName, topScores[count].difficulty, topScores[count].map); 
 | 
			
		||||
                count++;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // leave if MAX_PRINTED_SCORES is reached
 | 
			
		||||
            if(count >= MAX_PRINTED_SCORES)
 | 
			
		||||
            {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        highestPlayerScore--;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fclose(filePtr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//==========================
 | 
			
		||||
//==== readTop10Scores =====
 | 
			
		||||
//==========================
 | 
			
		||||
// return the number of various scores of the file
 | 
			
		||||
int countRecordsInFile(const char *filename) 
 | 
			
		||||
{
 | 
			
		||||
    FILE *file;
 | 
			
		||||
    file = fopen(filename, "rb");
 | 
			
		||||
 | 
			
		||||
    // failure
 | 
			
		||||
    if (file == NULL) 
 | 
			
		||||
    {
 | 
			
		||||
        LOGI("Datei: Fehler beim Öffnen der Datei!\n");
 | 
			
		||||
        return -1; 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fseek(file, 0, SEEK_END);    // Gehe zum Dateiende
 | 
			
		||||
    long fileSize = ftell(file); // Hole die Größe der Datei in Bytes
 | 
			
		||||
    fclose(file);
 | 
			
		||||
 | 
			
		||||
    int recordSize = sizeof(playerScore_t);
 | 
			
		||||
    int numberOfRecords = fileSize / recordSize; // Berechne die Anzahl der Datensätze
 | 
			
		||||
 | 
			
		||||
    return numberOfRecords;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										41
									
								
								src/game.c
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								src/game.c
									
									
									
									
									
								
							@ -5,6 +5,7 @@
 | 
			
		||||
#include "food.h"
 | 
			
		||||
#include "render.h"
 | 
			
		||||
#include "sound.h"
 | 
			
		||||
#include "files.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// global struct for storing all game data
 | 
			
		||||
@ -111,8 +112,10 @@ void runGameCycle()
 | 
			
		||||
        // TODO consider game.lifesRemaining and reset if still good?
 | 
			
		||||
        LOGI("game: collided with wall or self! => show leaderboard\n");
 | 
			
		||||
        //game.gameState = MENU; //TODO add config.collisionEnabled option?
 | 
			
		||||
        //savePlayerScore(/*(game.snake.length - config.snakeDefaultLength), ttlStorage.userName, config.difficulty, *storedMaps[ttlStorage.userSelectedMap - 1]*/);
 | 
			
		||||
        showLeaderboard();
 | 
			
		||||
        savePlayerScore("../build/player_scores.bin"/*(game.snake.length - config.snakeDefaultLength), ttlStorage.userName, config.difficulty, *storedMaps[ttlStorage.userSelectedMap - 1]*/);
 | 
			
		||||
        readTopScores("../build/player_scores.bin");
 | 
			
		||||
        game.gameState = MENU;
 | 
			
		||||
        activeMenu = LEADERBOARD;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -136,37 +139,3 @@ void runGameCycle()
 | 
			
		||||
#endif
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//==========================
 | 
			
		||||
//==== savePlayerScores ====
 | 
			
		||||
//==========================
 | 
			
		||||
// void savePlayerScore(/*int score, int difficulty, const char *playerName,  const char *map*/) 
 | 
			
		||||
// {   
 | 
			
		||||
//     // playerScore_t playerScore;
 | 
			
		||||
 | 
			
		||||
//     // // copy data into struct
 | 
			
		||||
//     // playerScore.score = game.snake.length - config.snakeDefaultLength;
 | 
			
		||||
//     // playerScore.difficulty = config.difficulty;
 | 
			
		||||
//     // strcpy(playerScore.playerName, ttlStorage.userName);
 | 
			
		||||
//     // strcpy(playerScore.map, "testmap");
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
//     // FILE *file;
 | 
			
		||||
//     // // open file
 | 
			
		||||
//     // file = fopen("../player_scores.bin", "ab");
 | 
			
		||||
 | 
			
		||||
//     // // write data in file
 | 
			
		||||
//     // if (file != NULL) 
 | 
			
		||||
//     // {
 | 
			
		||||
//     //     fwrite(&playerScore, sizeof(playerScore_t), 1, file);
 | 
			
		||||
//     //     fclose(file);
 | 
			
		||||
 | 
			
		||||
//     //     LOGI("Spielergebnis wurde erfolgreich in die Binärdatei gespeichert.\n");
 | 
			
		||||
//     // } 
 | 
			
		||||
//     // else 
 | 
			
		||||
//     // {
 | 
			
		||||
//     //     LOGI("Fehler beim Öffnen der Datei!\n");
 | 
			
		||||
//     // }
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -77,6 +77,7 @@ void showLeaderboard()
 | 
			
		||||
{
 | 
			
		||||
    LOGD("menu: showing leaderboard\n");
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    //--- play crash sound ---
 | 
			
		||||
    //play audio file, wait until playback is finished
 | 
			
		||||
    //note: when displaying actual leaderboard, the second parameter should be 'false' to not block the program
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user