Part3:The Menu State/Game Example

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

目录:

1、Game Example说明

2、The Menu State

3、补充 简单使用

1、Game Example说明

We have now covered everything that we need in order to create our game. This section explains important parts of the code but doesn't go into all the details here: There's a bit too much code to explain every single line of code in this article. However, the source code is fairly well commented so do not hesitate to take a deeper look.

The game is divided in three states: the menu state, the play state and the high-score state. As explained earlier, each of these states are handled in their own classes, which inherit from theCGameStateclass. Each of these classes are implemented as singletons.

There is a little addition in this game that is not available in its typical predecessors: A combo multiplier. Each time one (or several) line(s) is (are) completed, the player has a certain time to complete another line to multiply the score of the new completed line (or lines). The multiplier increases each time a new line has been completed before the combo time runs out. If the time runs out, the current muliplier is decreased by one and a new timer starts. Of course, the higher the multiplier is, the faster the time decrases.

2、The Menu State

This state displays the main menu with the following options: new game, resume game (if there is currently an active game), high scores and exit the game. The header file is:

// Specialization of the CGameState class for 
// the menu state. This displays a menu in which
// the player can start a new game, continue an 
// existing game, see the high-scores or exit the game.
class CMenuState : public CGameState
{
public:
  ~CMenuState();

  void OnKeyDown(WPARAM wKey);
  void Draw();
  void EnterState();

  static CMenuState* GetInstance(CStateManager* pManager);

protected:
  CMenuState(CStateManager* pManager);

private:
  // The player went up or down in 
  // the menu
  void SelectionUp();
  void SelectionDown();
  // The player validated the current selection
  void SelectionChosen();

  CGameFont* m_pFont;
  // Index of the current selected menu item
  int m_iCurrentSelection;

  // A pointer to the current active game (if any).
  CPlayState* m_pCurrentGame;

  // The background and title images
  TImagePtr m_pBackgroundImg;
  TImagePtr m_pTitleImg;

  // The images of the menu items (normal and
  // selected).
  TImagePtr m_pItemBckgndNormal;
  TImagePtr m_pItemBckgndSelected;

  // The text controls of the different entries.
  CTextControl* m_pNewGameText;
  CTextControl* m_pResumeGameText;
  CTextControl* m_pScoresText;
  CTextControl* m_pExitText;
};

SelectionUp, SelectionDown or SelectionChosenfunctions are called when the up, down or enter key is pressed. The selection up and down functions simply change them_iCurrentSelection index and theSelectionChosen function switches to another state or exit the game depending of the selected menu item.

The CTextControl is a simple utility class that displays text in a rectangle region with a certain alignment (left, center or right).

3、补充 简单使用

补充:CMenuState类的其它部分

注:1、析构函数中是否需要delete

        2、CImage::CreateImage():第二个参数是指要获取的图象,在整张图上的区域

              CTextControl():第二个参数是指文本在屏幕中输出的区域

CMenuState::CMenuState(CStateManager* pManager) 
  : CGameState(pManager), m_pFont(NULL), m_iCurrentSelection(0), 
    m_pCurrentGame(NULL)
{
	m_pFont = new CGameFont;
	m_pFont->CreateFont("Verdana", 30, FW_NORMAL);

	// Create the different images
	m_pBackgroundImg = CImage::CreateImage("MainBackground.png",TRectanglei(0,600,0,800));
	m_pTitleImg = CImage::CreateImage("MenuTitle.png",TRectanglei(0,600,0,800));
	m_pItemBckgndNormal = CImage::CreateImage("MenuItems.png",TRectanglei(0,57,0,382));
	m_pItemBckgndSelected = CImage::CreateImage("MenuItems.png",TRectanglei(58,114,0,382));

	// Create the text controls of the menu.
	m_pNewGameText = new CTextControl(m_pFont,TRectanglei(150,207,209,591));
	m_pNewGameText->SetAlignement(CTextControl::TACenter);
	m_pNewGameText->SetText("New game");
	m_pResumeGameText = new CTextControl(m_pFont,TRectanglei(250,307,209,591));
	m_pResumeGameText->SetAlignement(CTextControl::TACenter);
	m_pResumeGameText->SetText("Resume game");
	m_pScoresText = new CTextControl(m_pFont,TRectanglei(350,407,209,591));
	m_pScoresText->SetAlignement(CTextControl::TACenter);
	m_pScoresText->SetText("High scores");
	m_pExitText = new CTextControl(m_pFont,TRectanglei(450,507,209,591));
	m_pExitText->SetAlignement(CTextControl::TACenter);
	m_pExitText->SetText("Exit");
}

CMenuState::~CMenuState()
{
}

CMenuState* CMenuState::GetInstance(CStateManager* pManager)
{
	static CMenuState Instance(pManager);
	return &Instance;
}

void CMenuState::OnKeyDown(WPARAM wKey)
{
	switch (wKey)
	{
	case VK_DOWN:
		SelectionDown();
		break;
	case VK_UP:
		SelectionUp();
		break;
	case VK_RETURN:
		SelectionChosen();
		break;
	}
}

void CMenuState::Draw()
{
	m_pBackgroundImg->BlitImage();
	m_pTitleImg->BlitImage();
	// Draw the menu item backgrounds
	for (int i=0;i<4;i++)
	{
		if (i==m_iCurrentSelection)
			m_pItemBckgndSelected->BlitImage(209,150+i*100);
		else
			m_pItemBckgndNormal->BlitImage(209,150+i*100);
	}
	
	m_pNewGameText->Draw();
	m_pResumeGameText->Draw();
	m_pScoresText->Draw();
	m_pExitText->Draw();
}

void CMenuState::EnterState()
{
	// Checks whether there is a current game active
	m_iCurrentSelection = 0;
	if (!m_pCurrentGame || m_pCurrentGame->IsGameOver())
		m_pResumeGameText->SetTextColor(0.5,0.5,0.5);
	else
		m_pResumeGameText->SetTextColor(1.0,1.0,1.0);
}

void CMenuState::SelectionUp()
{
	m_iCurrentSelection--;
	if (m_iCurrentSelection==-1)
		m_iCurrentSelection = 3;

	// If there is no current game, we should skip
	// the "Resume game" item.
	if (m_iCurrentSelection==1) 
	{
		if (!m_pCurrentGame || m_pCurrentGame->IsGameOver())
			m_iCurrentSelection--;
	}
}

void CMenuState::SelectionDown()
{
	m_iCurrentSelection++;
	if (m_iCurrentSelection==4)
		m_iCurrentSelection = 0;

	// If there is no current game, we should skip
	// the "Resume game" item.
	if (m_iCurrentSelection==1) 
	{
		if (!m_pCurrentGame || m_pCurrentGame->IsGameOver())
			m_iCurrentSelection++;
	}
}

void CMenuState::SelectionChosen()
{
	switch (m_iCurrentSelection)
	{
	case 0:
		if (!m_pCurrentGame)
			m_pCurrentGame = CPlayState::GetInstance(m_pStateManager);
		m_pCurrentGame->Reset();
		ChangeState(m_pCurrentGame);
		break;

	case 1:
		if (m_pCurrentGame && !m_pCurrentGame->IsGameOver())
			ChangeState(m_pCurrentGame);
		break;

	case 2:
		ChangeState(CHighScoreState::GetInstance(m_pStateManager));
		break;

	case 3:
		PostQuitMessage(0);
		break;
	}
}

简单使用:

CStateManager *m_pStateManager;  
  
CMainWindow::CMainWindow(..)  
{  
//...  
    m_pStateManager = new CStateManager;  
    m_pStateManager->ChangeState(CMenuState::GetInstance(m_pStateManager));  
}  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值