Read/Write Offsets and Seeking

Storing Player Name

How could we modify the high score example to also store the player's name along with the score?

Abstract art representing computer programming

To store the player's name along with the score, you'll need to define a structure that holds both the name and the score. You'll also need to decide on a format for storing this data in the file.

Let’s see an example. First, we’ll define a structure:

#include <SDL.h>
#include <iostream>
#include <algorithm>
#include <string>

struct ScoreEntry {
  int32_t Score;
  
  // Assuming a maximum name length
  // of 49 characters + null terminator
  char Name[50];
};

Next, let’s modify UpdateHighScore():

void UpdateHighScore(
  const char* Path, const ScoreEntry& NewEntry
) {
  SDL_RWops* File{SDL_RWFromFile(Path, "w+b")};
  if (!File) {
    std::cerr << "Error opening file: "
      << SDL_GetError() << "\n";
    return;
  }

  const int NumScores{5};
  ScoreEntry HighScores[NumScores];

  size_t EntriesRead{SDL_RWread(
    File, HighScores,
    sizeof(ScoreEntry),
    NumScores
  )};

  if (EntriesRead < NumScores) {
    std::cout << "Initializing new high scores\n";
    for (size_t i{EntriesRead}; i<NumScores; ++i) {
      HighScores[i].Score = 0;

      // Initialize name to an empty string
      HighScores[i].Name[0] = '\0';
    }
  }

  bool IsHighScore{false};
  for (int i{0}; i < NumScores; ++i) {
    if (NewEntry.Score > HighScores[i].Score) {
      IsHighScore = true;
      break;
    }
  }

  if (IsHighScore) {
    std::cout << NewEntry.Name
      << " achieved a new high score of "
      << NewEntry.Score
      << "! Updating file\n";

    HighScores[NumScores - 1] = NewEntry;
    std::sort(HighScores, HighScores + NumScores,
      [](const ScoreEntry& a, const ScoreEntry& b) {
        return a.Score > b.Score;
      });

    SDL_RWseek(File, 0, RW_SEEK_SET);
    SDL_RWwrite(
      File, HighScores,
      sizeof(ScoreEntry), NumScores
    );
  } else {
    std::cout << "Not a high score - "
      "file not updated\n";
  }

  SDL_RWclose(File);
}

int main() {
  ScoreEntry ScoreOne{500, "Noob"};
  UpdateHighScore("highscores.dat", ScoreOne);
  ScoreEntry ScoreTwo{5000, "Alice"};
  UpdateHighScore("highscores.dat", ScoreTwo);
  ScoreEntry ScoreThree{3000, "Bob"};
  UpdateHighScore("highscores.dat", ScoreThree);
  ScoreEntry ScoreFour{6000, "Charlie"};
  UpdateHighScore("highscores.dat", ScoreFour);
  ScoreEntry ScoreFive{4000, "David"};
  UpdateHighScore("highscores.dat", ScoreFive);
  ScoreEntry ScoreSix{5500, "Eve"};
  UpdateHighScore("highscores.dat", ScoreSix);
  return 0;
}
Initializing new high scores
Noob achieved a new high score of 500! Updating file
Alice achieved a new high score of 5000! Updating file
Bob achieved a new high score of 3000! Updating file
Charlie achieved a new high score of 6000! Updating file
David achieved a new high score of 4000! Updating file
Eve achieved a new high score of 5500! Updating file

Explanation

  • We define a ScoreEntry struct to hold the player's name and score.
  • We use a fixed-size character array (char Name[50]) for the name, assuming a maximum length of 49 characters (plus the null terminator).
  • In UpdateHighScore(), we now read and write an array of ScoreEntry structs.
  • When initializing new entries, we set the Name field to an empty string.
  • When a new high score is achieved, we add the NewEntry to the HighScores array and sort the array based on the Score member using a lambda function for comparison.
  • We then write the entire sorted HighScores array back to the file.

Considerations

  • Fixed-Length Names: Using a fixed-size character array for the name simplifies the code but limits the length of names. You might consider using a more flexible approach, like storing the length of the name followed by the characters, but that would add complexity to the file format.
  • Error Handling: You might want to add error handling to deal with cases where the name is longer than the allowed length.
  • Alternative Data Formats: For more complex data structures, you might consider using a serialization library or a standard data format like JSON or XML, but that's beyond the scope of this simple example.

This example demonstrates a basic way to store both the player's name and score in the high score file. You can adapt this approach to handle more complex data structures or use different file formats based on your specific needs.

This Question is from the Lesson:

Read/Write Offsets and Seeking

Learn how to manipulate the read/write offset of an SDL_RWops object to control stream interactions.

Answers to questions are automatically generated and may not have been reviewed.

This Question is from the Lesson:

Read/Write Offsets and Seeking

Learn how to manipulate the read/write offset of an SDL_RWops object to control stream interactions.

sdl2-promo.jpg
Part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, unlimited access

This course includes:

  • 79 Lessons
  • 100+ Code Samples
  • 91% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2025 - All Rights Reserved