|
俄罗斯方块
相信许多人都玩过俄罗斯方块游戏,该游戏即可以锻炼反应能力,也可以提高思维能力。笔者小时候就为该游戏所痴迷,就梦想长大后也设计一个类似的游戏。如今选择了程序员的职业,自然可以实现这个“梦想”了。图1显示了笔者设计的俄罗斯方块游戏的效果图。
关键技术
在实现俄罗斯方块游戏时,涉及的技术比较简单,主要有两个,一是在绘制表格时使用内存画布来绘制表格,减少屏幕刷新次数,二是随机产生不同类型的方块。首先将所有的绘图操作在内存画布上完成,然后在内存画布对象释放时,将其内容绘制到窗口中,这样在窗口中只进行了一次绘图,减少了屏幕的刷新次数;其次在游戏过程中,需要产生不同类型的方块,为此需要编写一个方法,来生成方块。由于方块的基本类型只有7种,因此产生的类型必须在1到7之间。为此,需要使用随机函数rand与7进行取模运算。
在设计俄罗斯方块时,首先需要设计游戏的表格(CGrid类),游戏中的表格由单元格(CCell类)构成。在单元格对象中描述了所在表格的行和列索引,单元格是否被使用,单元格是否被固定(当图像移动到表格的底部,不能再向下移动了)等信息。
俄罗斯方块中共有7种基本形状,基本类型可以按90°旋转,这样又可以变换出12种新的类型,为这些形状统一建一个类CPiece。在CPiece类中,有一个关键的成员m_ImagesPT,该成员是一个数组,其中包含了4个CPoint对象。由于罗斯方块图像都占有4个单元格,因此使用4个CPoint对象描述每一个单元格坐标,这里的坐标是单元格的行和列索引。当游戏产生一个新的方块图像时,图像最左边的位置由m_nLeftIndex成员表示,顶部位置由m_nTopIndex成员表示。依据这两个成员和当前图像的类型
游戏中显示方块时,将遍历CPiece的m_ImagesPT成员,读取每个元素表示的单元格坐标,通过该坐标来定位表格中的单元格CCell,将单元格CCell的m_bUsed成员设置为TRUE,然后调用表格CGrid的DrawGrid来绘制表格,使得方块显示在表格中。
在游戏进行中,默认时方块会向下移动,用户也可以使用左右方向键来移动图像。为了能够移动图像,需要设置CPiece类的m_nLeftIndex成员和m_nTopIndex成员,然后重新设置CPiece类的m_ImagesPT成员,最后绘制表格就可以实现移动图像的效果了。
设计过程
(1)创建一个基于对话框的工程,工程名称为“RussianGrid”。
(2)向对话框中添加图片、按钮、静态文本和群组框的控件,
(3)向对话框中添加HorMovePiece方法,当用户按左右方向键时左右移动方块图像。其实现代码如下:
void CRussianGridDlg::HorMovePiece(int nOffset)
{
if (m_Piece.m_bMoving == FALSE) //方块是否处于移动过程中
{
return;
}
BOOL bLeftMove = (nOffset < 1)? TRUE: FALSE; //防止左右穿透图像
if (!m_pGrid->IsAllowHorMove(m_Piece, bLeftMove))
{
m_bKeyDown = FALSE; //如果不能左右移动,则在OnTimer中继续向下移动
return;
}
m_Piece.MovePiece(m_Piece.m_nLeftIndex + nOffset , m_Piece.m_nTopIndex);
for(int i=0; i<4; i++) //显示图像
{
int nX = m_Piece.m_ImagesPT.x;
int nY = m_Piece.m_ImagesPT.y;
m_pGrid->m_CellGrid[nY][nX].m_bUsed = TRUE;
}
m_pGrid->DrawGrid(GetDC()); //绘制表格
for( i=0; i<4; i++) //在绘制下一次图像时使之前的图像消失
{
int nX = m_Piece.m_ImagesPT.x;
int nY = m_Piece.m_ImagesPT.y;
m_pGrid->m_CellGrid[nY][nX].m_bUsed = FALSE;
}
//获取当前方块所在列对应的底部行索引
BOOL bRet = m_pGrid->GetBottomRowIndex(m_Piece.m_nLeftIndex, m_Piece.m_nWidth, m_Piece);
if (bRet)
{
for( i=0; i<4; i++)
{
int nX = m_Piece.m_ImagesPT.x;
int nY = m_Piece.m_ImagesPT.y;
m_pGrid->m_CellGrid[nY][nX].m_bUsed = FALSE;
if (m_nKeyDown > 3)
{
m_pGrid->m_CellGrid[nY][nX].m_bFixed = TRUE;
m_Piece.m_bMoving = FALSE;
GradeHandle(m_Piece); //计算成绩
if (GameOver()) //判断游戏是否结束
{
m_bGameRunning = FALSE;
MessageBox("游戏结束!");
}
}
}
}
}
秘笈心法
心法领悟596:FrameRect方法的使用
实例中使用CDC类的FrameRect方法绘制区域的边框,该方法同Draw3dRect方法类似,不同的是Draw3dRect方法将区域分为两组进行绘制显示立体效果,FrameRect方法使用一种颜色对区域四周进行绘制。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|