目录:
1、CTetrad_Z类具体实现
2、CTetradFactory类的实现
3、CComboControl类的实现
1、CTetrad_Z类具体实现
CTetrad_Z类是方块中的一种,继承自CTetrad类。其它的实现类似
class CTetrad_Z : public CTetrad
{
public:
CTetrad_Z(CBlocksMatrix* pParent);
~CTetrad_Z();
bool Rotate();
bool MoveLeft();
bool MoveRight();
bool MoveDown();
void FillMatrix();
bool IsValid();
void Draw();
void DrawOnScreen(const TRectanglei& rect);
};
CTetrad_Z::CTetrad_Z(CBlocksMatrix* pParent) : CTetrad(pParent,bcRed)
{
}
CTetrad_Z::~CTetrad_Z()
{
}
bool CTetrad_Z::Rotate()
{
bool bSuccess = false;
switch (m_Orientation)
{
case Rotation0:
case Rotation180:
if (m_pParentMatrix->IsCellFree(m_iXPos,m_iYPos-1) &&
m_pParentMatrix->IsCellFree(m_iXPos-1,m_iYPos+1) )
{
m_Orientation = Rotation90;
bSuccess = true;
}
break;
case Rotation90:
case Rotation270:
if (m_pParentMatrix->IsCellFree(m_iXPos,m_iYPos+1) &&
m_pParentMatrix->IsCellFree(m_iXPos+1,m_iYPos+1))
{
m_Orientation = Rotation0;
bSuccess = true;
}
break;
}
return bSuccess;
}
bool CTetrad_Z::MoveLeft()
{
bool bSuccess = false;
switch (m_Orientation)
{
case Rotation0:
case Rotation180:
if (m_pParentMatrix->IsCellFree(m_iXPos-2,m_iYPos) &&
m_pParentMatrix->IsCellFree(m_iXPos-1,m_iYPos+1))
{
m_iXPos--;
bSuccess = true;
}
break;
case Rotation90:
case Rotation270:
if (m_pParentMatrix->IsCellFree(m_iXPos-1,m_iYPos-1) &&
m_pParentMatrix->IsCellFree(m_iXPos-2,m_iYPos ) &&
m_pParentMatrix->IsCellFree(m_iXPos-2,m_iYPos+1) )
{
m_iXPos--;
bSuccess = true;
}
break;
}
return bSuccess;
}
bool CTetrad_Z::MoveRight()
{
bool bSuccess = false;
switch (m_Orientation)
{
case Rotation0:
case Rotation180:
if (m_pParentMatrix->IsCellFree(m_iXPos+1,m_iYPos) &&
m_pParentMatrix->IsCellFree(m_iXPos+2,m_iYPos+1))
{
m_iXPos++;
bSuccess = true;
}
break;
case Rotation90:
case Rotation270:
if (m_pParentMatrix->IsCellFree(m_iXPos+1,m_iYPos-1) &&
m_pParentMatrix->IsCellFree(m_iXPos+1,m_iYPos ) &&
m_pParentMatrix->IsCellFree(m_iXPos,m_iYPos+1) )
{
m_iXPos++;
bSuccess = true;
}
break;
}
return bSuccess;
}
bool CTetrad_Z::MoveDown()
{
bool bSuccess = false;
switch (m_Orientation)
{
case Rotation0:
case Rotation180:
if (m_pParentMatrix->IsCellFree(m_iXPos-1,m_iYPos+1) &&
m_pParentMatrix->IsCellFree(m_iXPos ,m_iYPos+2) &&
m_pParentMatrix->IsCellFree(m_iXPos+1,m_iYPos+2) )
{
m_iYPos++;
bSuccess = true;
}
break;
case Rotation90:
case Rotation270:
if (m_pParentMatrix->IsCellFree(m_iXPos-1,m_iYPos+2) &&
m_pParentMatrix->IsCellFree(m_iXPos,m_iYPos+1))
{
m_iYPos++;
bSuccess = true;
}
break;
}
return bSuccess;
}
void CTetrad_Z::Draw()
{
int screenX=0, screenY=0;
switch (m_Orientation)
{
case Rotation0:
case Rotation180:
m_pParentMatrix->GetScreenPosFromCell(m_iXPos-1,m_iYPos,screenX,screenY);
m_pBlockImg->BlitImage(screenX,screenY);
m_pParentMatrix->GetScreenPosFromCell(m_iXPos ,m_iYPos,screenX,screenY);
m_pBlockImg->BlitImage(screenX,screenY);
m_pParentMatrix->GetScreenPosFromCell(m_iXPos ,m_iYPos+1,screenX,screenY);
m_pBlockImg->BlitImage(screenX,screenY);
m_pParentMatrix->GetScreenPosFromCell(m_iXPos+1,m_iYPos+1,screenX,screenY);
m_pBlockImg->BlitImage(screenX,screenY);
break;
case Rotation90:
case Rotation270:
m_pParentMatrix->GetScreenPosFromCell(m_iXPos ,m_iYPos-1,screenX,screenY);
m_pBlockImg->BlitImage(screenX,screenY);
m_pParentMatrix->GetScreenPosFromCell(m_iXPos ,m_iYPos ,screenX,screenY);
m_pBlockImg->BlitImage(screenX,screenY);
m_pParentMatrix->GetScreenPosFromCell(m_iXPos-1,m_iYPos ,screenX,screenY);
m_pBlockImg->BlitImage(screenX,screenY);
m_pParentMatrix->GetScreenPosFromCell(m_iXPos-1,m_iYPos+1,screenX,screenY);
m_pBlockImg->BlitImage(screenX,screenY);
break;
}
}
void CTetrad_Z::DrawOnScreen(const TRectanglei& rect)
{
int XPos = (rect.GetWidth() - 3*BLOCK_WIDTH)/2 + rect.m_Left;
int YPos = (rect.GetHeight() - 2*BLOCK_HEIGHT)/2 + rect.m_Top;
m_pBlockImg->BlitImage(XPos,YPos);
m_pBlockImg->BlitImage(XPos+BLOCK_WIDTH,YPos);
m_pBlockImg->BlitImage(XPos+BLOCK_WIDTH,YPos+BLOCK_HEIGHT);
m_pBlockImg->BlitImage(XPos+2*BLOCK_WIDTH,YPos+BLOCK_HEIGHT);
}
void CTetrad_Z::FillMatrix()
{
switch (m_Orientation)
{
case Rotation0:
case Rotation180:
m_pParentMatrix->FillCell(m_iXPos-1,m_iYPos,m_BlockColor);
m_pParentMatrix->FillCell(m_iXPos ,m_iYPos,m_BlockColor);
m_pParentMatrix->FillCell(m_iXPos ,m_iYPos+1,m_BlockColor);
m_pParentMatrix->FillCell(m_iXPos+1,m_iYPos+1,m_BlockColor);
break;
case Rotation90:
case Rotation270:
m_pParentMatrix->FillCell(m_iXPos ,m_iYPos-1,m_BlockColor);
m_pParentMatrix->FillCell(m_iXPos ,m_iYPos ,m_BlockColor);
m_pParentMatrix->FillCell(m_iXPos-1,m_iYPos ,m_BlockColor);
m_pParentMatrix->FillCell(m_iXPos-1,m_iYPos+1,m_BlockColor);
break;
}
}
bool CTetrad_Z::IsValid()
{
bool bValid = false;
if (m_pParentMatrix->IsCellFree(m_iXPos-1,m_iYPos) &&
m_pParentMatrix->IsCellFree(m_iXPos ,m_iYPos) &&
m_pParentMatrix->IsCellFree(m_iXPos ,m_iYPos+1) &&
m_pParentMatrix->IsCellFree(m_iXPos+1,m_iYPos+1) )
{
bValid = true;
}
return bValid;
}
2、CTetradFactory类的实现
CTetradFactory类用来生成方块
// This class simply creates random tetrads.
class CTetradFactory
{
public:
CTetradFactory();
~CTetradFactory();
CTetrad* CreateTetrad(CBlocksMatrix* pMatrix);
};
CTetradFactory::CTetradFactory()
{
//time(NULL):1970年1月1日00:00:00以来的秒数
//设置随机数种子
srand ( (unsigned int)time(NULL) );
}
CTetradFactory::~CTetradFactory()
{
}
CTetrad* CTetradFactory::CreateTetrad(CBlocksMatrix* pMatrix)
{
CTetrad* pNewTetrad = NULL;
int value = rand()%7;
switch (value)
{
case 0:
pNewTetrad = new CTetrad_I(pMatrix);
break;
case 1:
pNewTetrad = new CTetrad_O(pMatrix);
break;
case 2:
pNewTetrad = new CTetrad_S(pMatrix);
break;
case 3:
pNewTetrad = new CTetrad_Z(pMatrix);
break;
case 4:
pNewTetrad = new CTetrad_T(pMatrix);
break;
case 5:
pNewTetrad = new CTetrad_J(pMatrix);
break;
case 6:
pNewTetrad = new CTetrad_L(pMatrix);
break;
}
return pNewTetrad;
}
简单应用:
// The tetrad factory
CTetradFactory m_TetradFactory;
m_pTetrad = m_TetradFactory.CreateTetrad(this);
m_pNextShape = m_TetradFactory.CreateTetrad(this);
3、CComboControl类的实现
CComboControl类是一个辅助,增加游戏的趣味性。在相应的时间消掉一行,m_iMultiplier就会增加,相应的分数也会成倍增加。
// Class which handles the combo control: this
// control shows a decreasing time bar when a line
// has been completed. If a new line is completed
// before time is over, a multiplier is applied to the
// points gained for the line(s) completed. The higher
// the multiplier, the fastest time will decrease.
class CComboControl
{
public:
CComboControl(const TRectanglei& rectControl, CGameFont* pFont);
~CComboControl();
// Updates and draw the control
void Update(unsigned long dwCurrentTime);
void Draw();
// Increases the current multiplier and starts
// a new timer which depends of the multiplier
void IncreaseMultiplier();
int GetMultiplier() const { return m_iMultiplier; }
void Reset();
void Pause();
void Unpause();
private:
// Returns the total time available for
// the current multiplier.
int GetMultiplierTime() const;
// The current combo multiplier
int m_iMultiplier;
// Time left for the current combo
int m_iTimeLeft;
// Total time for the current combo
int m_iTotalTime;
// The last time at which the control was updated
unsigned long m_iLastUpdate;
// true if the control is paused (time doesn't
// decrease anymore)
bool m_bPaused;
// The font used by the control
CGameFont* m_pFont;
// The rectangle of the control
TRectanglei m_rectControl;
TImagePtr m_pProgressBorder;
TImagePtr m_pProgressFill;
};
CComboControl::CComboControl(const TRectanglei& rectControl, CGameFont* pFont)
: m_iMultiplier(1), m_iTimeLeft(0), m_iTotalTime(0),
m_iLastUpdate(0), m_bPaused(false), m_pFont(pFont),
m_rectControl(rectControl)
{
m_pProgressBorder = CImage::CreateImage("ProgressBar.png",TRectanglei(0,24,0,126));
m_pProgressFill = CImage::CreateImage("ProgressBar.png",TRectanglei(27,51,0,126));
}
CComboControl::~CComboControl()
{
if (m_pFont)
{
delete m_pFont;
m_pFont = NULL;
}
}
void CComboControl::Pause()
{
m_bPaused = true;
}
void CComboControl::Unpause()
{
m_iLastUpdate = GetCurrentTime();
m_bPaused = false;
}
void CComboControl::Update(unsigned long dwCurrentTime)
{
if (m_iMultiplier == 1)
return;
if (m_bPaused)
return;
int dwTimeDiff = dwCurrentTime - m_iLastUpdate;
if (dwTimeDiff >= m_iTimeLeft)
{
m_iMultiplier--;
if (m_iMultiplier != 1)
m_iTimeLeft = m_iTotalTime = GetMultiplierTime();
else
m_iTimeLeft = m_iTotalTime = 0;
}
else
m_iTimeLeft -= dwTimeDiff;
m_iLastUpdate = dwCurrentTime;
}
void CComboControl::Draw()
{
stringstream ssText;
ssText << "Multiplier: X" << m_iMultiplier;
m_pFont->DrawText(ssText.str(),m_rectControl.m_Left+25,
m_rectControl.m_Top+60,1.0f,0.588f,0.039f);
float barPercent = 0;
if (m_iTotalTime!=0)
barPercent = (float)m_iTimeLeft/m_iTotalTime;
else
barPercent = 0;
TRectanglei fill(0,24,0,(int)(126*barPercent));
m_pProgressFill->BlitImagePart(85,405,fill);
m_pProgressBorder->BlitImage(85,405);
}
void CComboControl::IncreaseMultiplier()
{
if (m_iMultiplier<10)
m_iMultiplier++;
m_iTotalTime = m_iTimeLeft = GetMultiplierTime();
m_iLastUpdate = GetCurrentTime();
}
int CComboControl::GetMultiplierTime() const
{
return 20000 - (m_iMultiplier-2)*2000;
}
void CComboControl::Reset()
{
m_iMultiplier = 1;
m_iTotalTime = m_iTimeLeft = 0;
m_iLastUpdate = 0;
}