来自: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 theCGameState
class. 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 SelectionChosen
functions 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));
}