Part3:The High-Scores State

来自: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 the m_bEnterName flag is true, characters will be added to the m_pCurrentName array, until the user presses enter. In that case, the AddNewScorefunction 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);
		}
	}
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值