Part3:The High-Scores State

来源:互联网 发布:软件摊销年限 税法 编辑:程序博客网 时间:2024/05/23 16:48

来自:http://www.codeproject.com/Articles/30775/TetroGL-An-OpenGL-Game-Tutorial-in-C-for-Win32-pla

目录:

1、The High-Scores State

2、简单使用

1、The High-Scores State

This state is responsible to display the high-scores which are saved from previous games. The information is saved in a file for persistency ("HighScores.txt"). The file is not protected, so anybody can edit this file and change the high-scores. This is of course not very nice but describing ways to protect this data is outside the scope of the article. As usual, I'll first show the class declaration before going into some details:

// Specialization of the CGameState class for // the high scores state. This displays the high// scores (player name+score). When a new high // score is available after a game, it lets the // player enters his name.class CHighScoreState : public CGameState{public:  ~CHighScoreState();  // Sets a new score: if this score should be   // part of the high scores, the user will need   // to enter his name.  void SetNewHighScore(ULONG ulNewHighScore)    { m_ulNewHighScore = ulNewHighScore; }  // Implementation of specific events  void OnKeyDown(WPARAM wKey);  void OnChar(WPARAM wChar);  void Draw();  void EnterState();  static CHighScoreState* GetInstance(CStateManager* pManager);protected:  CHighScoreState(CStateManager* pManager);private:  // Saves the current high scores  void SaveScores();  // Adds a new score in the high-score table and  // insert it at the correct location.  void AddNewScore(const std::string& strName, ULONG ulScore);  // High-score data: score and player name.  struct HighScoreData  {    std::string strPlayer;    ULONG ulScore;    // We have to sort in decreasing order, so the <    // operator returns the opposite.    bool operator< (const HighScoreData& other)    {      if  (this->ulScore > other.ulScore)         return true;      return false;    }  };  // The new high-score, if any.  ULONG m_ulNewHighScore;  // Mode in which the user has to enter his name.  bool m_bEnterName;  // Char array containing the name currently being entered.  char m_pCurrentName[26];  // The index of the next char to be entered.  int m_iNameIndex;  CGameFont* m_pFont;  typedef std::vector<HighScoreData> THighScoreTable;  // The high-score table.  THighScoreTable m_vecHighScores;  // The background and title images.  TImagePtr m_pBackgroundImg;   TImagePtr m_pTitleImg;   // The image of the entries background  TImagePtr m_pEntriesBckgndImg;  // The 'Enter name' image and the background.  TImagePtr m_pEnterNameImg;   TImagePtr m_pEnterNameBackImg; };
The class overrides the EnterState function, it is used to read the high-scores from the file and check if a new high-score should be added in the table:

void CHighScoreState::EnterState(){  // Clear the high-score table  m_vecHighScores.clear();  ifstream inputFile("HighScores.txt");  if (inputFile.fail())  {    if (m_ulNewHighScore)      m_bEnterName = true;    return;  }  // Read all entries from the file  while (!inputFile.eof())  {    HighScoreData newScore;    inputFile >> newScore.strPlayer >> newScore.ulScore;    m_vecHighScores.push_back(newScore);  }  // Sort the table  sort(m_vecHighScores.begin(), m_vecHighScores.end());  // Check if we have a new high-score that should be  // added in the table. If yes, m_bEnterName is set  // to true.  ULONG lastScore = 0;  if (m_vecHighScores.size())    lastScore = m_vecHighScores[m_vecHighScores.size()-1].ulScore;  if (m_ulNewHighScore && m_ulNewHighScore>lastScore)    m_bEnterName = true;}

When reading the file, we sort the high-scores using the std::sort function. For that purpose, we should provide an operator< for our structure. The std::sort function sorts the elements in ascending order, that's the reason our operator returns the opposite of what is excepted (so that all elements are ordered in the opposite order). When characters are inserted by the user, the OnCharfunction is called. If them_bEnterName flag is true, characters will be added to them_pCurrentName array, until the user presses enter. In that case, theAddNewScorefunction is called:

void CHighScoreState::AddNewScore(const std::string& strName, ULONG ulScore){  // Create a new high-score and push it into the table   HighScoreData newData;  newData.strPlayer = strName;  newData.ulScore = ulScore;  m_vecHighScores.push_back(newData);    // Sort the table  sort(m_vecHighScores.begin(), m_vecHighScores.end());  // If too much elements, remove the last one.  while (m_vecHighScores.size() > 10)    m_vecHighScores.pop_back();  SaveScores();}

The SaveScores is called at the end to save the new high scores in the file:

void CHighScoreState::SaveScores(){  // Create the file  ofstream outputFile("HighScores.txt");  if (outputFile.fail())    return;  // Write all the entries in the file.  THighScoreTable::iterator iter = m_vecHighScores.begin();  for (iter; iter != m_vecHighScores.end(); iter++)  {    outputFile << iter->strPlayer << " " << iter->ulScore;  }}

In normal mode (when the name is not entered), the user can exit the high-score state and return to the main menu by pressing enter or escape.

//原文 end

2、简单使用

void CMenuState::SelectionChosen(){switch (m_iCurrentSelection){//...case 2:ChangeState(CHighScoreState::GetInstance(m_pStateManager));break;        //...}}
void CPlayState::OnKeyDown(WPARAM wKey){switch (wKey){//...case VK_RETURN:if (m_bGameOver){CHighScoreState* pHighScores = CHighScoreState::GetInstance(m_pStateManager);pHighScores->SetNewHighScore(m_ulCurrentScore);ChangeState(pHighScores);}}}





原创粉丝点击