www.pudn.com > TetrisWang.zip > Game.cpp
// Game.cpp: implementation of the CGame class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Tetris.h"
#include "Game.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
int CGame::m_nGameType = CGame::TYPE_SINGLE; // 游戏类型--单人
BOOL CGame::m_bComputerCanFallDown = TRUE; // 电脑可按“下”
int CGame::m_nComputerIntelligence= 2;
int CGame::m_nTetrisColor = 0;
CGame::CGame()
{
m_nScore = 0;
m_nLines = 0;
m_nSpeed = 0;
m_bWin = false;
m_bComputer = false;
m_nTetrisType = TETRIS_BASE;
m_nTetrisColor = COLOR_OWNE;
m_nStatus = STATUS_WAIT;
m_bActive = false;
}
CGame::CGame(CGame &g)
{
m_Body = g.m_Body;
m_Tetris = g.m_Tetris;
m_ptStart = g.m_ptStart;
m_nStatus = g.m_nStatus;
m_nScore = g.m_nScore;
m_nLines = g.m_nLines;
m_nSpeed = g.m_nSpeed;
m_pView = g.m_pView;
m_bWin = g.m_bWin;
m_bComputer = g.m_bComputer;
m_nTetrisType = g.m_nTetrisType;
m_bActive = g.m_bActive;
m_nIndex = g.m_nIndex;
for (int i=0; i<4; i++)
m_CtrlKeys[i] = g.m_CtrlKeys[i];
}
CGame::~CGame()
{
}
CSize CGame::MatchKey(UINT nChar)
{
CSize sz = CSize(-1, -1);
int nIndex;
if (IsComputer()) return sz;
for (nIndex=0; nIndex<4; nIndex++)
{
if (m_CtrlKeys[nIndex] == nChar) break;
if (nChar > 64 && nChar < 91) // 大写字母
{
if (m_CtrlKeys[nIndex] == nChar+32) break;
}
else if (nChar > 96 && nChar < 123) // 小写字母
{
if (m_CtrlKeys[nIndex] == nChar-32) break;
}
}
switch (nIndex)
{
case 0: // move left
sz = CSize(-1, 0);
break;
case 1: // move right
sz = CSize(1, 0);
break;
case 2: // roate
sz = CSize(0, 0);
break;
case 3: // fall down
sz = CSize(1, 1);
break;
default:
sz = CSize(-1, -1);
}
return sz;
}
CSize CGame::GetTopSize(void)
{
return CSize(m_Body.GetWidth() * CBlock::GetCell() + 2, 5 * CBlock::GetCell());
}
CSize CGame::GetBodySize(void)
{
return CSize(m_Body.GetWidth() * CBlock::GetCell() + 2, m_Body.GetHeight() * CBlock::GetCell() + 2);
}
CSize CGame::GetSize(void)
{
return CSize(m_Body.GetWidth() * CBlock::GetCell() + 2, (m_Body.GetHeight()+5) * CBlock::GetCell() + 2);
}
void CGame::Draw(CDC &dc)
{
if (m_nStatus == STATUS_WAIT)
{
DrawGameWait(dc);
return;
}
DrawTop(dc);
m_Body.Draw(dc);
if (m_nStatus == STATUS_OVER) DrawGameOver(dc);
}
void CGame::DrawTop(CDC &dc)
{
int nSaveDC = dc.SaveDC();
dc.SelectStockObject(BLACK_PEN);
dc.SelectStockObject(WHITE_BRUSH);
dc.SetBkColor(RGB(255, 255, 255));
dc.Rectangle(CRect(m_ptStart, GetTopSize()));
dc.Rectangle(CRect(m_ptStart+CSize(0, GetTopSize().cy), GetBodySize()));
CString strTitle;
CString strValue;
CFont font;
font.CreatePointFont(CBlock::GetCell()*6, "宋体");
dc.SelectObject(&font);
// strTitle.LoadString(IDS_SCORE);
strTitle = GetLangueString("Score");
strValue.Format("%8d", m_nScore);
dc.TextOut(m_ptStart.x + CBlock::GetCell() * 5, m_ptStart.y + CBlock::GetCell() / 2, LPCTSTR(strTitle));
dc.TextOut(m_ptStart.x + CBlock::GetCell() * 6, m_ptStart.y + CBlock::GetCell() + CBlock::GetCell() / 2, LPCTSTR(strValue));
// strTitle.LoadString(IDS_LINES);
strTitle = GetLangueString("Lines");
strValue.Format("%8d", m_nLines);
dc.TextOut(m_ptStart.x + CBlock::GetCell() * 6, m_ptStart.y + CBlock::GetCell() * 2 + CBlock::GetCell() / 2, LPCTSTR(strValue));
dc.TextOut(m_ptStart.x + CBlock::GetCell() * 5, m_ptStart.y + CBlock::GetCell() * 2 + CBlock::GetCell() / 2, LPCTSTR(strTitle));
// strTitle.LoadString(IDS_SPEED);
strTitle = GetLangueString("Speed");
strValue.Format("%8d", m_nSpeed);
dc.TextOut(m_ptStart.x + CBlock::GetCell() * 6, m_ptStart.y + CBlock::GetCell() * 3 + CBlock::GetCell() / 2, LPCTSTR(strValue));
dc.TextOut(m_ptStart.x + CBlock::GetCell() * 5, m_ptStart.y + CBlock::GetCell() * 3 + CBlock::GetCell() / 2, LPCTSTR(strTitle));
font.DeleteObject();
m_Tetris.Draw(m_ptStart+CSize(CBlock::GetCell(), CBlock::GetCell()/2), dc);
dc.RestoreDC(nSaveDC);
}
void CGame::DrawGameOver(CDC& dc)
{
int nSaveDC = dc.SaveDC();
dc.SetBkMode(TRANSPARENT);
CFont font;
font.CreatePointFont(CBlock::GetCell()*(CTetrisApp::m_nLangue == CTetrisApp::CHINESE ? 16 : 16), "宋体");
dc.SelectObject(&font);
CString strOut;
if (!m_bWin)
{
// strOut.LoadString(IDS_GAMEOVER);
dc.SetTextColor(RGB(0, 0, 255));
strOut = GetLangueString("GameOver");
}
else
{
// strOut.LoadString(IDS_GAMEWIN);
strOut = GetLangueString("GameWin");
dc.SetTextColor(RGB(255, 0, 0));
}
dc.DrawText(strOut, CRect(m_ptStart, GetSize()), DT_VCENTER | DT_CENTER | DT_NOCLIP | DT_SINGLELINE);
font.DeleteObject();
dc.RestoreDC(nSaveDC);
}
void CGame::DrawGameWait(CDC& dc)
{
int nSaveDC = dc.SaveDC();
dc.SetBkMode(TRANSPARENT);
CFont font;
font.CreatePointFont(CBlock::GetCell()*(CTetrisApp::m_nLangue == CTetrisApp::CHINESE ? 14 : 22), "宋体");
dc.SelectObject(&font);
CString strOut;
// strOut.LoadString(IDS_GAMEWAIT);
strOut = GetLangueString("GameWait");
dc.SetTextColor(RGB(0, 0, 255));
dc.DrawText(strOut, CRect(m_ptStart, GetBodySize()), DT_VCENTER | DT_CENTER | DT_NOCLIP | DT_SINGLELINE);
font.DeleteObject();
CFont lfont;
lfont.CreatePointFont(CBlock::GetCell()*6, "宋体");
dc.SelectObject(&lfont);
strOut.LoadString(IDS_COPYRIGHT);
dc.SetTextColor(RGB(0, 0, 255));
dc.DrawText(strOut, CRect(m_ptStart, GetSize()), DT_VCENTER | DT_CENTER | DT_NOCLIP | DT_SINGLELINE);
lfont.DeleteObject();
dc.RestoreDC(nSaveDC);
}
void CGame::StartGame(int nSpeed, int nLines, int nTetrisType, UINT nCtrlKeys[MAX_CTRL_KEYS], int nColorType)
{
m_nStatus = STATUS_RUN;
m_bWin = false;
m_nSpeed = nSpeed;
m_nLines = 0;
m_nTetrisType = nTetrisType;
m_nTetrisColor = nColorType;
m_Body.SetPoint(m_ptStart+CSize(1, GetTopSize().cy+1));
for (int i=0; iKillTimer(TimerIndex);
m_pView->SetTimer(TimerIndex, SpeedToTime(m_nSpeed), NULL);
}
void CGame::EndGame(BOOL bReDraw)
{
m_Body.CutLastTetris();
m_nStatus = STATUS_OVER;
UINT TimerIndex;
if (GetIndex() != 0)
TimerIndex = TIMER_INDEX_2;
else
TimerIndex = TIMER_INDEX_1;
m_pView->KillTimer(TimerIndex);
if (IsComputer()) m_pView->KillTimer(TIMER_COMPUTER);
if (bReDraw)
{
CClientDC dc(m_pView);
DrawGameOver(dc);
if (m_nGameType == TYPE_SITZKRIEG || m_nGameType == TYPE_COMPUTER)
m_pView->GameWin(m_nIndex);
}
}
void CGame::NewTetris(void)
{
int nTetris = rand() % m_nTetrisType;
int nColor;
switch (m_nTetrisColor)
{
case COLOR_OWNE:
nColor = nTetris;
break;
case COLOR_SAME:
nColor = 0;
break;
case COLOR_RAND:
nColor = rand() % MAX_COLORS;
break;
default:
nColor = 0;
}
m_Tetris = CTetris(nTetris, nColor);
}
void CGame::NextTetris(void)
{
m_Body.SetTetris(m_Tetris);
m_Body.SetTetrisPoint(CPoint(2, 0));
NewTetris();
}
void CGame::TetrisMove(const CSize &sz)
{
CClientDC dc(m_pView);
if (sz == CSize(0, 1)) // Tetris Down
{
if (!m_Body.TetrisMove(dc, sz))
{
TetrisDown(dc);
}
}
else if (sz == CSize(1, 1)) // Tetris Fall
{
for (int i=1; ; i++)
{
if (!m_Body.TetrisMove(dc, CSize(0, 1)))
{
TetrisDown(dc);
break;
}
}
}
else if (sz == CSize(0, 0)) // Tetris Roate
{
m_Body.TetrisMove(dc, sz);
}
else if (sz == CSize(-1, 0) || sz == CSize(1, 0)) // Tetris Move Left or Right
{
m_Body.TetrisMove(dc, sz);
}
}
void CGame::TetrisDown(CDC& dc)
{
NextTetris();
int nLines = m_Body.RemoveLines();
if (nLines > 0)
{
if (m_nLines / LINES_CHANGE_SPEED < (m_nLines + nLines) / LINES_CHANGE_SPEED)
{
if (m_nSpeed < MAX_SPEED)
{
m_nSpeed++;
SetGameTimer();
}
}
m_nLines += nLines;
m_nScore += LinesToScore(nLines);
if (nLines > 1 && (m_nGameType == TYPE_SITZKRIEG || m_nGameType == TYPE_COMPUTER))
m_pView->GameAddLines(GetIndex(), nLines);
}
if (!m_Body.IsTetrisFit(m_Body.GetTetrisPoint(), m_Body.GetTetris()))
{
EndGame();
}
Draw(dc);
if ((GetType() == TYPE_COMPUTER || GetType() == TYPE_TEACH) && IsComputer() && GetStatus() == STATUS_RUN)
SetComputerCtrl();
}
void CGame::AddLines(int nLines)
{
if (m_nStatus != STATUS_RUN) return;
if (nLines <= 0) return;
CClientDC dc(m_pView);
m_Body.AddLines(nLines, m_nTetrisType);
for (int i=0; im_nComputerIntelligence);
m_nCtrlRoate = nRoate;
m_nCtrlMove = nMove;
m_pView->SetTimer(TIMER_COMPUTER, SpeedToTime(9), NULL);
}
void CGame::ComputerCtrlTetris(void)
{
if (m_nCtrlRoate == 0 && m_nCtrlMove == 0) return;
if (m_nCtrlRoate > 0)
{
TetrisMove(CSize(0, 0));
m_nCtrlRoate--;
}
else if (m_nCtrlMove != 0)
{
TetrisMove(CSize(m_nCtrlMove/abs(m_nCtrlMove), 0));
m_nCtrlMove -= m_nCtrlMove/abs(m_nCtrlMove);
if (m_nCtrlMove == 0) m_pView->KillTimer(TIMER_COMPUTER);
}
}
UINT CGame::SpeedToTime(int nSpeed)
{
switch (nSpeed)
{
case 0:
return(1000);
case 1:
return(900);
case 2:
return(800);
case 3:
return(700);
case 4:
return(600);
case 5:
return(500);
case 6:
return(400);
case 7:
return(300);
case 8:
return(200);
case 9:
return(150);
}
return(150);
}
int CGame::LinesToScore(int nLines)
{
int nScore;
switch (nLines)
{
case 1:
nScore = 100;
break;
case 2:
nScore = 300;
break;
case 3:
nScore = 500;
break;
case 4:
nScore = 1000;
break;
}
return nScore;
}