📄 russian.cpp
字号:
//===============================================================================================
#include "Russian.h"
//================================================================================================
//类的实现
//===============================================================================================
//===============================================================================================
//静态变量初始化
int RussianCube::m_iShapeCode[] = {
0x145, //0
0x123,0x48c, //1 , 2
0x159,0x2456,0x489,0x124, //3,4,5,6
0x148,0x126,0x1589,0x456, //7,8,9 10
0x125,0x1459,0x1456,0x458, //11,12,13,14
0x459,0x1245, //15,16
0x1458,0x156 //17,18;
};
//construction
RussianCube::RussianCube(int iRow,int iColumn,HWND hWindow)
{
m_iRow = iRow; //行
m_iColumn = iColumn; //列
m_hWindow = hWindow; //窗口句柄
m_bShouldStop = false; //方块不停止
m_iLevel = 1; //等级为1
m_iScore = 0; //得分清零
m_iVolecity = 2;
m_iNext = rand() % 19; //生成第一个方块;
//创建背景和方块
HDC hDC = GetDC(hWindow);
m_pBackground = new Bitmap(hDC,IDB_BACKGROUND,g_hInstance);
m_pCubePic[0] = new Bitmap(hDC,IDB_CUBE1,g_hInstance);
m_pCubePic[1] = new Bitmap(hDC,IDB_CUBE2,g_hInstance);
m_pCubePic[2] = new Bitmap(hDC,IDB_CUBE3,g_hInstance);
m_pCubePic[3] = new Bitmap(hDC,IDB_CUBE4,g_hInstance);
m_pCube = new bool*[m_iRow]; //分配二维数组;
for(int i = 0; i < m_iRow; ++i)
{
m_pCube[i] = new bool [m_iColumn];
}
//不显示所有方块
for(i = 0; i< m_iRow; ++i)
{
for(int j = 0; j < m_iColumn; ++j)
{
m_pCube[i][j] = false;
}
}
Refresh(); //刷新生成新的方块;
}
//distruction
RussianCube::~RussianCube()
{
delete m_pBackground;
delete m_pCubePic[0];
delete m_pCubePic[1];
delete m_pCubePic[2];
delete m_pCubePic[3];
for(int i = 0 ;i < m_iRow; ++ i)
{
delete []m_pCube[i];
}
delete []m_pCube;
}
//刷新生成新的方块
void RussianCube::Refresh(void)
{
m_ptMain.y = 0;
m_ptMain.x = m_iColumn / 2 * m_pCubePic[0]->GetWidth();
m_iShape = m_iNext;
m_iNext = rand() % 19;
Calculation(); //计算方块的的位置;
}
//绘制
void RussianCube::Draw(HDC hDC)
{
m_pBackground->Draw(hDC,0,0); //背景
int iWidth = m_pCubePic[0]->GetWidth();
int iHeight = m_pCubePic[0]->GetHeight();
for(int iRow = 0; iRow < m_iRow; ++iRow) //从左到右每一列扫描方块
{
for(int iColumn = 0 ; iColumn < m_iColumn;++iColumn)
{
if(m_pCube[iRow][iColumn]) //如果该位置不为空
{
m_pCubePic[rand() % 4]->Draw(hDC, iColumn * iWidth ,iRow * iHeight );
}
}
}
for(int i = 0; i < 4; ++i) //绘制四个小方块组成的图形
{
m_pCubePic[rand() % 4]->Draw(hDC,m_ptCube[i].x,m_ptCube[i].y);
}
//计算并绘制下一个方块
POINT ptNext[4];
int iTempShape = m_iShapeCode[m_iNext]; //译码
int iBit;//取位
i = 0;
while(iTempShape && i < 4)//计算四个方块的坐标
{
iBit = iTempShape % 16;
ptNext[i].x = (iBit % 4) * iWidth + 211;
ptNext[i].y = (iBit / 4) * iHeight + 60;
++i;
iTempShape /=16;
}
if(i <= 3)
{
ptNext[3].x = 211;
ptNext[3].y = 60;
}
for(i = 0; i < 4; ++i) //绘制四个小方块组成的图形
{
m_pCubePic[rand() % 4]->Draw(hDC,ptNext[i].x,ptNext[i].y);
}
//显示得分
char szMessage[64];
wsprintf(szMessage,"%d",m_iScore);
TextOut(hDC,249,218,szMessage,strlen(szMessage));
//显示等级
wsprintf(szMessage,"%d",m_iLevel);
TextOut(hDC,249,300,szMessage,strlen(szMessage));
if(IsGameOver())
{
TextOut(hDC,60,140,TEXT("GAME OVER !!"),12);
}
}
//方块下落
void RussianCube::FallDown(void)
{
for(int i = 0; i < 4; ++i)
{
m_ptCube[i].y += m_iVolecity;
}
m_ptMain.y += m_iVolecity;
}
//是否可以左移
bool RussianCube::CanLeft(void)
{
int iHeight = m_pCubePic[0]->GetHeight();
int iWidth = m_pCubePic[0]->GetWidth();
for(int i = 0; i < 4; ++i)
{
//如果方块没有到达边界,并且左边没有方块
if(m_ptCube[i].x <= 0 || m_pCube[m_ptCube[i].y /iHeight][m_ptCube[i].x / iWidth -1] )
{
return false;
}
}
return true;
}
//是否可以右移
bool RussianCube::CanRight()
{
int iHeight = m_pCubePic[0]->GetHeight();
int iWidth = m_pCubePic[0]->GetWidth();
for(int i = 0; i < 4; ++i)
{
//如果方块没有到达边界,并且右边没有方块
if(m_ptCube[i].x >= 180 || m_pCube[m_ptCube[i].y /iHeight][m_ptCube[i].x / iWidth + 1])
{
return false;
}
}
return true;
}
//游戏是否结束
bool RussianCube::IsGameOver(void)
{
for(int iX = 0; iX < m_iColumn; ++iX)
{
if(m_pCube[0][iX]) //如果顶部已经有方块,游戏结束
{
return true;
}
}
return false;
}
//变形
void RussianCube::Change(void)
{
switch(m_iShape)
{
case 1:case 2:
if(m_ptMain.x <= 120)
{
if(m_iShape == 1)
{
m_iShape = 2;
}
else
{
m_iShape = 1;
}
}
break;
case 3: case 4: case 5: case 6:
if(m_ptMain.x <= 140)
{
m_iShape += 1;
}
if(m_iShape > 6)
{
m_iShape = 3;
}
break;
case 7: case 8: case 9: case 10:
if(m_ptMain.x <= 140)
{
m_iShape += 1;
}
if(m_iShape > 10)
{
m_iShape = 7;
}
break;
case 11: case 12: case 13: case 14:
if(m_ptMain.x <= 140)
{
m_iShape += 1;
}
if(m_iShape > 14)
{
m_iShape = 11;
}
break;
case 15: case 16:
if(m_ptMain.x <= 140)
{
if(m_iShape == 15)
{
m_iShape = 16;
}
else
{
m_iShape = 15;
}
}
break;
case 17: case 18:
if(m_ptMain.x <= 140)
{
if(m_iShape == 17)
{
m_iShape = 18;
}
else
{
m_iShape = 17;
}
}
break;
default: //
break;
}
}
//保存坐标
void RussianCube::SaveCoordinate(void)
{
int iWidth = m_pCubePic[0]->GetWidth();
int iHeight = m_pCubePic[0]->GetHeight();
for(int i = 0; i < 4; ++i)
{
m_pCube[m_ptCube[i].y / iHeight][m_ptCube[i].x / iWidth] = true;
}
//扫描方块,是否已经填满
for(int y = m_iRow-1; y >= 0; --y) //扫描Y轴
{
for(int x = 0; x < m_iColumn; ++x) //扫描X轴
{
if(!m_pCube[y][x])//如果还有空白,
{
break;
}
}
if(x >= m_iColumn)// 如果没有空白,则消除这一行
{
PlaySound((LPCSTR)IDW_ELIMINATE,g_hInstance,SND_ASYNC | SND_RESOURCE);
m_iScore += 10; //得分增加
for(int i = y; i > 0; --i)
{
for(int j = 0; j < m_iColumn; ++j)
{
m_pCube[i][j] = m_pCube[i-1][j];
}
}
y++;
}
}
}
//计算坐标
void RussianCube::Calculation(void)
{
int iTempShape = m_iShapeCode[m_iShape]; //译码
int iBit;//取位
int i = 0;
int iWidth = m_pCubePic[0]->GetWidth();
int iHeight = m_pCubePic[0]->GetHeight();
while(iTempShape && i < 4)//计算四个方块的坐标
{
iBit = iTempShape % 16;
m_ptCube[i].x = (iBit % 4) * iWidth + m_ptMain.x;
m_ptCube[i].y = (iBit / 4) * iHeight + m_ptMain.y;
++i;
iTempShape /=16;
}
if(i <= 3)
{
m_ptCube[3].x = m_ptMain.x;
m_ptCube[3].y = m_ptMain.y;
}
}
//左右 或下移动方块
void RussianCube::SetDrection(int iDrection)
{
PlaySound((LPCSTR)IDW_KEYS,g_hInstance,SND_ASYNC | SND_RESOURCE);
int iWidth = m_pCubePic[0]->GetWidth();
int iHeight = m_pCubePic[0]->GetHeight();
int iDown; //向下的偏移量
int iTemp = 0; //各块向下量
int i,iX,iY;
switch(iDrection)
{
case LEFT: //左移
if(CanLeft()) //如果还能左移
{
m_ptMain.x -= iWidth;
m_ptCube[0].x -= iWidth;
m_ptCube[1].x -= iWidth;
m_ptCube[2].x -= iWidth;
m_ptCube[3].x -= iWidth;
}
break;
case RIGHT: //右移
if(CanRight()) //如果还能左移
{
m_ptMain.x += iWidth;
m_ptCube[0].x += iWidth;
m_ptCube[1].x += iWidth;
m_ptCube[2].x += iWidth;
m_ptCube[3].x += iWidth;
}
break;
case CHANGE: //变形
Change(); //进行方块变换
Calculation(); //重新计算坐标
break;
case DOWN: //向下
iDown = 40; //向下偏移量为最大
for( i = 0; i < 4; ++i)
{
iY = m_ptCube[i].y / iHeight + 1;
iX = m_ptCube[i].x / iWidth;
iTemp = 0;
while(iY < m_iRow && !m_pCube[iY][iX] )
{
++iY;
++iTemp;
}
if(iTemp < iDown )
{
iDown = iTemp;
}
}
m_ptMain.y += iDown * iHeight;
m_ptCube[0].y += iDown * iHeight;
m_ptCube[1].y += iDown * iHeight;
m_ptCube[2].y += iDown * iHeight;
m_ptCube[3].y += iDown * iHeight;
break;
default:
break;
}
}
//方块是否应该停止
bool RussianCube::ShouldStop(void)
{
int iHeight = m_pCubePic[0]->GetHeight();
int iWidth = m_pCubePic[0]->GetWidth();
for(int i = 0; i < 4; ++i)
{
int iY = m_ptCube[i].y / iHeight + 1;
int iX = m_ptCube[i].x / iWidth;
//取坐标
if(iY == m_iRow) //方块已经到窗口底部
{
return true;
}
else if(m_pCube[iY][iX]) //下面已经有方块
{
return true;
}
}
return false;
}
//===============================================================================================
//游戏初始化
bool GameInitialize(HINSTANCE hInstance)
{
//创建游戏引擎
g_pGame = new GameEngine(hInstance,TEXT("RUSSIAN CUBE"),TEXT("RUSSIAN CUBE"),IDI_RUSSIAN,
IDI_RUSSIAN_SM,300,400);
if(g_pGame==NULL)
{
return false;
}
g_hInstance = hInstance;
g_pGame->SetFrameRate(15); //设置帧频
return true;
}
//=================================================================================================
//游戏开始
void GameStart(HWND hWindow)
{
srand(GetTickCount());
//20行,10列
g_pRussian = new RussianCube(20,10,hWindow);
}
//===================================================================================================
//游戏结束
void GameEnd(void)
{
delete g_pGame;
delete g_pRussian;
}
//=================================================================================================
//游戏绘制
void GamePaint(HDC hDC)
{
g_pRussian->Draw(hDC);
}
//==================================================================================================
//游戏循环
void GameCycle(void)
{
if(!g_pRussian->IsGameOver())
{
if(!g_pRussian->ShouldStop()) //如果方块还不应该停止
{
g_pRussian->FallDown(); //方块继续下落
}
else
{
g_pRussian->SaveCoordinate(); //保存小方块的坐标;
//随机生成新的方块
g_pRussian->Refresh();
}
InvalidateRect(g_pGame->GetWindow(),NULL,false);
}
else
{
PlaySound((LPCSTR)IDW_GAMEOVER,g_hInstance,SND_ASYNC | SND_RESOURCE);
g_pGame->SetSleep(true);
//TCHAR szMessage[64];
//wsprintf(szMessage,"GAME OVER !");
//MessageBox(g_pGame->GetWindow(),szMessage,TEXT("俄罗斯方块"),MB_OK);
}
}
//=================================================================================================
//激活与停用
void GameActivate(HWND hWindow)
{}
void GameDeactivate(HWND hWindow)
{}
//===================================================================================================
//处理键盘输入
void HandleKeys(void)
{
if(GetAsyncKeyState(VK_LEFT) < 0)
{
g_pRussian->SetDrection(LEFT);
}
else if(GetAsyncKeyState(VK_RIGHT) < 0)
{
g_pRussian->SetDrection(RIGHT);
}
else if(GetAsyncKeyState(VK_UP) < 0)
{
g_pRussian->SetDrection(CHANGE);
}
else if(GetAsyncKeyState(VK_DOWN)< 0)
{
g_pRussian->SetDrection(DOWN);
}
}
//===================================================================================================
//鼠标左键
void MouseButtonDown(int x, int y, bool bLeft)
{}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -