c++图形学实验教程:游戏程序实例(最终稿)_第1页
c++图形学实验教程:游戏程序实例(最终稿)_第2页
c++图形学实验教程:游戏程序实例(最终稿)_第3页
c++图形学实验教程:游戏程序实例(最终稿)_第4页
c++图形学实验教程:游戏程序实例(最终稿)_第5页
已阅读5页,还剩25页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、游戏程序实例“俄罗斯方块”是大家熟知的一款小游戏。本章将以“俄罗斯方块”为实例讲解如何利用C+语言开发平台编写Windows游戏。之所以选择以“俄罗斯方块”为例,就在于它简单、易读、易实现。当读者读完本章时,将能亲手完成游戏程序的编写,在理解游戏编写细节的同时,也能体会游戏开发的乐趣。“俄罗斯方块”游戏的玩法简单易学。运行游戏程序以后,首先用左右方向键或“M”、“N”键设置游戏的等级。右方向键或“M”键是等级提升1级,左方向键或“N”键是等级降低1级。设置好玩家需要的等级以后,单击“开始”按钮或按“A”键,这个时候方块开始下落。在游戏的过程中,左、右方向键控制方块的左、右移动;向下的方向键是使

2、方块直接下落到底部;向上的方向键控制方块的逆时针旋转,每按一次向上的方向键逆时针旋转90度。在游戏的过程中,如果玩家不想游戏,想休息一下的话,可以单击“暂停”按钮或按“P”键,这个时候,游戏就会暂时停止。当玩家再次单击“暂停”或再次按“P”键的时候,游戏又会继续运行。需要说明的是,如果玩家在游戏的过程中,觉得当前的游戏等级不是很满意,可以在游戏中进行等级的更改设置。方法是游戏中用左、右两个方向键或“M”、“N”键更改游戏的等级。游戏方法可总结为 REF _Ref200770342 h * MERGEFORMAT 表 1。表 SEQ 表 * ARABIC 1 游戏方法操作功能按“A”键或“开始”

3、按钮开始游戏按“P”键或“暂停”按钮暂停/继续游戏按“R”键重新开始游戏按“N”键方块减速下落按“M”键方块加速下落按“”键游戏状态,方块左移;其它状态,减速按“”键游戏状态,方块右移;其它状态,加速按“”键下落按“”键逆时针旋转90度为说明方便,将本章内出现的俄罗斯方块游戏中各部分的名称分别在 REF _Ref200770446 h 图 1和 REF _Ref200770448 h 图 2中标出。图 SEQ 图 * ARABIC 1 名称说明1图 SEQ 图 * ARABIC 2 名称说明2第一节 程序构建过程首先打开Microsoft Visual C+ 6.0。单击“File”“New”

4、。这个时候就会出现“New”对话框。在“New”对话框中,选择“Projects”表单。在“Projects”表单的列表框里选择“MFC AppWizard(exe)”,然后在名称里面输入程序的名称,“俄罗斯方块”游戏程序的名称是“Tetris”。然后在“Location”里面输入保存的路径。整个过程如 REF _Ref200770534 h 图 3所示。图 SEQ 图 * ARABIC 3 创建新工程然后单击“确定”,这个时候会出现“MFC AppWizard”对话框,选择“Dialog based”,即“俄罗斯方块”游戏程序是建立在对话框界面上的。如 REF _Ref200770642 h

5、 图 4所示。图 SEQ 图 * ARABIC 4 创建基于对话框的界面然后点击“Finish”按钮,系统会弹出一个对话框,列出了用户在创建工程时的一些预选信息。点击“OK”后,就会生成相应的程序包。当完成以上的操作以后,程序会自动生成一个工程,包括一个对话框界面。编译之后,如 REF _Ref200770731 h 图 5所示。图 SEQ 图 * ARABIC 5 创建后自动生成的对话框接下来,就需要布置一下游戏的界面。在“Workspace”子窗口中,选择 “Dialog”资源,在展开的树形结构中点击相应的对话框IDD_TETRIS_DIALOG,在右侧窗口中便显示出相应的对话框编辑器。布

6、置控件的方法需要使用控件面板,如 REF _Ref200770803 h 图 6所示。图 SEQ 图 * ARABIC 6 对话框资源编辑界面只要用鼠标单击控件,然后拖到图形面板上相应的位置就可以了。首先要删除对话框中的所有控件,并增加如下控件。各个控件的主要属性如下:控件ButtonIDIDC_STARTCaption开始控件ButtonIDIDC_PAUSECaption暂停控件ButtonIDIDC_ABORTCaption结束控件ButtonIDIDC_ABOUTCaption帮助控件ButtonIDIDC_EXITCaption退出控件TextIDIDC_SCORE_STATICCa

7、ption分数控件TextIDIDC_LEVEL_STATICCaption等级布置好的界面如 REF _Ref200770862 h 图 7所示。图 SEQ 图 * ARABIC 7 对话框编辑后的界面设置好以后,就要实现程序的代码部分。第二节 源代码注释首先对全局常量进行声明。#defineSHAPE( 7 )/方块的种类为7种,形状分别为:图 SEQ 图 * ARABIC 8 俄罗斯方块的形状#defineDIRECTION( 4 )/方块的方向,即每一种方块四个方向。例如: 方向1 方向2 方向3 方向4图 SEQ 图 * ARABIC 9 俄罗斯方块的方向#defineCELLROW

8、( 4 )/方块格的行数#defineCELLCOL( 4 )/方块格的列数44的方块格可以完全包括所有类型的方块。一个方块由四个方格按不同位置组成,最长的是这种形状,图 SEQ 图 * ARABIC 10 最长(高)的俄罗斯方块因此在44的方块格中可以表示任意形状和方向的方块。#defineROW( 24 )/面板格子的行数#defineCOL( 12 )/面板格子的列数面板是方块下落和堆积的区域。#defineLEN( 18 )/每个方块格的边长为18个像素。接下来,定义一个名为CPiece的类,由该类来负责绘制每片方块。显然,有关方块的形状、方向、颜色等信息将出现在该类中;同时,将由该类

9、的成员函数负责完成单片方块的绘制工作。完整的类定义为:class CPiece : public CObject public:CPiece();/构造函数virtual CPiece();/析构函数CPiece( const CPiece &sp ); /重载构造函数operator=( const CPiece &sp ); /重载赋值运算public:voidInitData();/对方块数据初始化voidNewPiece();/产生新的方块数据public:voidDrawPiece( CDC *pDC, CRect windowRect, bool bErase = false );

10、/绘制方块static voidDrawCell( CDC *pDC, CPoint ptLocal, COLORREF clr, CRect windowRect, bool bErase = false ); /绘制方格private:intm_nShape;/方块的形状信息intm_nDirection;/方块的方向信息CPointm_ptCurPosition;/方块的当前位置intm_nDataCELLROWCELLCOL;/下落方块的数据COLORREF m_clrData;/方块的颜色信息friend class CTetrisDlg;CPiece类中有5个私有成员变量:变量m_

11、nShape保存的是方块的形状,其合法值为06;变量m_nDirection保存的是方块的方向,其合法值为03;变量m_ptCurPosition保存的是方块左上角在面板中的位置,由它来记录方块的下落路径;数组m_nData保存的是下落方块的数据;变量m_clrData保存的是方块的颜色。请注意,CTetrisDlg类是CPiece类的友元,这就意味着,CPiece类可以访问CTetrisDlg类中的私有成员,这为两类之间的数据交换提供了方便。CPiece()和CPiece( const CPiece &sp )是CPiece类的两个构造函数,分别定义如下:/=/构造函数:/形状为无效(-1)

12、;/ 方向为无效(-1);/ 位置为上部居中。/=CPiece:CPiece()/形状变量初始化为-1,06为合法值。m_nShape= -1;/方向变量初始化为-1,03为合法值。m_nDirection= -1;/方块下落的初始位置为面板顶部中间位置。m_ptCurPosition= CPoint( COL / 2 - 2, 0 ); /=/复制构造函数:/const CPiece &sp:为原方块/=CPiece:CPiece( const CPiece &sp )/复制m_nShape成员变量(方块的形状);m_nShape= sp.m_nShape;/复制m_nDirection成员

13、变量(方块的方向);m_nDirection= sp.m_nDirection;/复制m_ptCurPosition成员变量(方块左上角的当前位置);m_ptCurPosition= sp.m_ptCurPosition;/数据初始化;InitData();/复制m_clrData成员变量(方块的颜色);m_clrData= sp.m_clrData;在CPiece类中,还有一个重载的赋值运算,其函数与复制构造函数完全一样。在定义了重载的赋值运算之后,就可以方便地初始化或修改一个CPiece实例了。/=/重载赋值运算:/ const CPiece &sp 为原方块/=CPiece:operat

14、or =(const CPiece &sp )/复制m_nShape成员变量(方块的形状);m_nShape= sp.m_nShape;/复制m_nDirection成员变量(方块的方向);m_nDirection= sp.m_nDirection;/复制m_ptCurPosition成员变量(方块左上角的当前位置);m_ptCurPosition= sp.m_ptCurPosition;/数据初始化;InitData();/复制m_clrData成员变量(方块的颜色);m_clrData = sp.m_clrData;在CPiece类中,4个私有成员函数。说明如下。InitData()函数是

15、对成员数组m_nDataCELLROWCELLCOL进行初始化的函数。在该数组中保存的是即将下落的方块的数据。/=/初始化形状数据/保存在3 3的9个比特位中/=void CPiece:InitData()/ nData中保存有所有可能的不同形状和方向的方块。int nData4 = / 0000111100000000, 0100010001000100, 0000111100000000, 0100010001000100 , 0 x0f00, 0 x4444, 0 x0f00, 0 x4444 ,/ 0100010001100000, 0010111000000000, 11000100

16、01000000, 0000111010000000 , 0 x4460, 0 x2e00, 0 xc440, 0 x0e80 ,/ 0100010011000000, 0000111000100000, 0110010001000000, 1000111000000000 , 0 x44c0, 0 x0e20, 0 x6440, 0 x8e00 ,/ 1100110000000000, 1100110000000000, 1100110000000000, 1100110000000000 , 0 xcc00, 0 xcc00, 0 xcc00, 0 xcc00 ,/ 11000110000

17、00000, 0010011001000000, 1100011000000000, 0010011001000000 , 0 xc600, 0 x2640, 0 xc600, 0 x2640 ,/ 0110110000000000, 0100011000100000, 0110110000000000, 0100011000100000 , 0 x6c00, 0 x4620, 0 x6c00, 0 x4620 ,/ 0000111001000000, 0100011001000000, 0100111000000000, 0100110001000000 ; 0 x0e40, 0 x4640

18、, 0 x4e00, 0 x4c40 ;int Data = nDatam_nShapem_nDirection;/ Data保存的是即将下落的方块的数据。/将Data保存到m_nData中,在Data保存的1位数据在转换到m_nData中变为1个字节的数据。int nShift = CELLROW * CELLCOL - 1;for(int i = 0; i CELLROW; i+)for(int j = 0; j CELLCOL; j+)/通过右移,将Data保存的1位数据变为m_nData中的1个字节的数据。转换的数据按Data中由高到低的位顺序进行,因此右移位数的值nShift由大到小

19、变化。m_nDataij = (Data & (1 nShift; nShift-;/=/新建一个方块/ 初始化方块的形状,/ 初始化方块的方向,/ 初始化方块的当前位置,/ 初始化方块的颜色,/ 对所有可能的形状和方向数据初始化。/=void CPiece:NewPiece()m_nShape= rand() % SHAPE;/ 方块的形状数据随机产生。m_nDirection= rand() % DIRECTION; / 方块的方向数据随机产生。m_ptCurPosition= CPoint( COL + 1, 1 ); / 方块的当前位置设定在提示区域。m_clrData= RGB( r

20、and()%255,rand()%255,rand()%255 ); / 方块的颜色数据随机产生。InitData();/对m_nData数组中的数据进行初始化。/=/绘制方块中的一个方格;/CDC *pDC:设备环境类指针;/ CPoint ptLocal:方块左上角在面板中的位置;/ COLORREF clr:俄罗斯方块的颜色;/ CRect windowRect:绘制窗口;/ bool bErase:是否擦除? bErase = true 则以背景色擦除该方块/=void CPiece:DrawCell( CDC *pDC, CPoint ptLocal, COLORREF clr, C

21、Rect windowRect, bool bErase/*= false*/ )CPointptTL, ptBR;intnCol, nRow;nCol = ptLocal.x;/保存方块左上角在面板中位置的x坐标(以方块为单位)nRow = ptLocal.y; /保存方块左上角在面板中位置的y坐标(以方块为单位)ptTL.x= windowRect.left + nCol * LEN;/ 保存方块左上角在用户区域中位置的x坐标(以像素为单位)ptTL.y= windowRect.top + nRow * LEN;/ 保存方块左上角在用户区域中位置的y坐标(以像素为单位)ptBR.x= pt

22、TL.x + LEN; / 保存方块右下角在用户区域中位置的x坐标(以像素为单位)ptBR.y= ptTL.y + LEN; / 保存方块右下角在用户区域中位置的y坐标(以像素为单位)CRectrtCell( ptTL, ptBR );/ rtCell中保存的是填充矩形的坐标。if( bErase )/如果擦除方格,则以系统颜色(即背景颜色)填充方格pDC-FillRect( &rtCell, &CBrush(GetSysColor(COLOR_3DFACE) );else/如果画新的方格,方格内部以参数clr所指定的颜色加以填充;/方格四边留有1像素宽的边框,/左边框和上边框涂白色;右边框和

23、下边框涂灰色,以显示立体效果。/留出边框位置(1个像素宽)ptTL.x +;ptTL.y +;ptBR.x -;ptBR.y -;/设置方格内部区域对应的矩形rtCell.SetRect( ptTL, ptBR );/以参数clr所指定的颜色,填充方格内部区域对应的矩形pDC-FillRect( &rtCell, &CBrush( clr ) );/创建白色画笔CPenpnWhite( PS_SOLID, 1, RGB(255,255,255) );/创建灰色画笔CPenpnGray( PS_SOLID, 1, RGB(0,0,0) );CPen*pOld = NULL;/选择白色画笔pOld

24、 = pDC-SelectObject( &pnWhite );/用白色画笔,画上边框pDC-MoveTo( ptTL.x, ptBR.y );pDC-LineTo( ptTL );/用白色画笔,画左边框pDC-LineTo( ptBR.x, ptTL.y );/选择灰色画笔pDC-SelectObject( &pnGray );/用灰色画笔,画下边框pDC-LineTo( ptBR );/用灰色画笔,画右边框pDC-LineTo( ptTL.x, ptBR.y );/恢复原先的画笔pDC-SelectObject( pOld );/释放画笔资源pnGray.DeleteObject();pn

25、White.DeleteObject();/=/绘制一个方块 /CDC *pDC:设备环境类指针;/CRect windowRect:绘制窗口;/ bool bErase:是否擦除? bErase = true 则以背景色擦除该方块/=void CPiece:DrawPiece( CDC *pDC, CRect windowRect, bool bErase/*= false*/ )CPointptLocal;/循环遍历方块中所有的方格位置for( int nRow = 0; nRow CELLROW; nRow + )for( int nCol = 0; nCol CELLCOL; nCol

26、 + )/计算方块中每一方格的位置坐标(以方格为单位)ptLocal.x = m_ptCurPosition.x + nCol;ptLocal.y = m_ptCurPosition.y + nRow;if( m_nDatanRownCol )/如果m_nDatanRownCol为1,表明是俄罗斯方块中的方格,加以绘制;如果为0,表明是背景,无需绘制。DrawCell( pDC, ptLocal, m_clrData, windowRect, bErase );在定义完CPiece的类之后,就可以向CTetrisDlg类添加代码了。在CTetrisDlg类中需要使用CPiece类的对象,因此在

27、TetrisDlg.h头文件中添加一行代码:#include PieceShape.hCTetrisDlg类是工程创建过程中生成的类,它主要负责对话框的显示和交互。俄罗斯方块游戏的主要功能将在CTetrisDlg类中加以完成。首先看一下CTetrisDlg类的定义,然后对类中的成员变量和成员函数分别加以说明。#defineST_PRE( 0 )/游戏状态,0:游戏未开始或游戏结束状态。#defineST_PLAY( 1 )/游戏状态,1:游戏进行状态。#defineST_PAUSE( 2 )/游戏状态,2:游戏暂停状态。#defineTOPMARGIN( 12 )/游戏区域相对于用户区域的上边

28、距#defineLEFTMARGIN( 12 )/游戏区域相对于用户区域的左边距#defineLEVELMAX( 10 )/游戏最高等级数#defineDELAYPERLEVEL ( 80 )/速度参数,即方块移动的时间间隔变化幅度(以毫秒计)#defineSCOREPERLEVEL ( 50 )/游戏晋级的分数间隔,即每增加多少分,游戏升高一级#defineELAPSEMAX( 1000 )/初始速度参数,即游戏开始时方块移动的时间间隔(以毫秒计)#include Piece.h/ CTetrisDlg dialogclass CTetrisDlg : public CDialog/ Con

29、structionpublic:CTetrisDlg(CWnd* pParent = NULL);/ standard constructor/ Dialog Data/AFX_DATA(CTetrisDlg)enum IDD = IDD_TETRIS_DIALOG ;/AFX_DATA/ ClassWizard generated virtual function overrides/AFX_VIRTUAL(CTetrisDlg)public:virtual BOOL PreTranslateMessage(MSG* pMsg);/ 消息的预处理。protected:virtual void

30、 DoDataExchange(CDataExchange* pDX);/ DDX/DDV support/AFX_VIRTUALpublic:voidStartGame();/开始游戏voidPauseGame();/暂停游戏voidResumeGame();/继续游戏voidAbortGame();/结束游戏voidStartDrop( CDC *pDC );/当前方块开始下落voidDrop();/当前方块下落voidFinishDrop( CDC *pDC );/当前方块结束下落boolMove( int nMode );/ 方块的移动。boolMoveValid( CPiece sp

31、 ); /检测方块位置是否有效,包括越界检测和与已落方块重叠检测。voidDrawRow( CDC *pDC, int nRow, bool bErase = false );/绘制面板中的一行。voidClearRow( int nTop, int nBotton );/满行时,清行voidFlashRow( CDC *pDC, CUIntArray &anRow );/被清掉的行的闪烁intGetState();/获得游戏状态voidSetShape( int nID );/设置方块的形状,即用数字键人为控制待落方块的形状voidSpeedUp();/加速下落voidSpeedDown()

32、;/减速下落private:intm_nScores;/游戏分数intm_nElapse;/方块移动的时间间隔(以毫秒计)intm_nLevel;/游戏等级(010级)intm_nState;/游戏状态(0:游戏未开始或游戏结束;1:游戏进行;2:游戏暂停;)CPiecem_Piece;/下落的俄罗斯方块的形状;CPiecem_NextPiece; /下一片俄罗斯方块的形状;boolm_DataROWCOL;/面板中方格数据,true代表有方块;false代表无方块。COLORREFm_clrDataROWCOL;/ 面板中方格颜色数据CRectm_rctDisplay;/面板显示区域/ Im

33、plementationprotected:HICON m_hIcon;/ Generated message map functions/AFX_MSG(CTetrisDlg)virtual BOOL OnInitDialog();/ 对话框初始化。afx_msg void OnPaint();/ 绘图消息响应函数。afx_msg void OnAbout();/ 按帮助按钮的消息响应函数,弹出About对话框。afx_msg void OnStart();/ 按开始按钮的消息响应函数,开始游戏。afx_msg void OnPause();/ 按暂停按钮的消息响应函数,暂停游戏或继续游戏。

34、afx_msg void OnAbort();/ 按结束按钮的消息响应函数,结束游戏。afx_msg void OnTimer(UINT nIDEvent);/ 定时器消息响应函数。afx_msg BOOL OnEraseBkgnd(CDC* pDC);/删除背景/AFX_MSGDECLARE_MESSAGE_MAP();/=/ 对话框初始化/=BOOL CTetrisDlg:OnInitDialog()CDialog:OnInitDialog();/ Set the icon for this dialog. The framework does this automatically/ wh

35、en the applications main window is not a dialogSetIcon(m_hIcon, TRUE);/ Set big iconSetIcon(m_hIcon, FALSE);/ Set small iconsrand( (unsigned)time(NULL) );/以系统时间为参数设定随机种子。/将m_Data数组中的元素初始化为false,即整个面板在初始时无方块。for( int nRowIndex = 0; nRowIndex ROW; nRowIndex + )for( int nColIndex = 0; nColIndex COL; nC

36、olIndex + )m_DatanRowIndexnColIndex = false;m_NextPiece.NewPiece();/产生一个新的方块,保存于m_NextPiece.实例中。m_nScores= 0;/初始分数为0。m_nLevel= 0;/初始等级为0。m_nElapse= ELAPSEMAX; /方块移动的时间间隔初始化为1000(以毫秒计)m_nState= ST_PRE;/游戏状态初始化为0,即游戏未开始或结束。m_rctDisplay = CRect(LEFTMARGIN,TOPMARGIN,LEFTMARGIN + COL * LEN,TOPMARGIN + RO

37、W * LEN);/面板显示区域初始化,相对于用户区域留有一定边距。return TRUE; / return TRUE unless you set the focus to a control/=/ 绘图消息响应函数/=void CTetrisDlg:OnPaint() if (IsIconic()CPaintDC dc(this); / device context for paintingSendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);/ Center icon in client rectangleint cxI

38、con = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;/ DrawPiece the icondc.DrawIcon(x, y, m_hIcon);elseCPaintDC dc(this);/声明设备环境对象实例。CBrush*pOld = NULL;/声明画刷指针。pOld

39、 = (CBrush *)dc.SelectStockObject( NULL_BRUSH ); /选择空画刷,即在绘制封闭区域时,不做任何颜色的填充。dc.Rectangle(m_rctDisplay.left - 1, m_rctDisplay.top - 1, m_rctDisplay.right + 1, m_rctDisplay.bottom + 1);/绘制面板显示区域矩形,即方块下落的游戏区域。dc.SelectObject( pOld );/恢复原来的画笔/显示游戏分数和游戏等级CStringstr;str.Format( 分数:%d, m_nScores );SetDlgIt

40、emText(IDC_SCORE_STATIC, str ); /显示游戏分数str.Format( 等级:%d, m_nLevel );SetDlgItemText(IDC_LEVEL_STATIC, str ); /显示游戏等级for( int nRow = 0; nRow FillRect( rt, &CBrush(GetSysColor(COLOR_3DFACE);return CDialog:OnEraseBkgnd(pDC);/=/ 消息的预处理,这里主要处理按键消息/=BOOL CTetrisDlg:PreTranslateMessage(MSG* pMsg) if( pMsg-

41、message = WM_KEYDOWN )/处理按键消息switch( pMsg-wParam )case VK_LEFT:/按键。if( GetState() = ST_PLAY )/如果是游戏状态,方块左移Move( 0 );else /否则,降低游戏级别,减慢方块下落速度SpeedDown();break;case VK_RIGHT: /按键。if( GetState() = ST_PLAY ) /如果是游戏状态,方块右移Move( 1 );else /否则,提高游戏级别,加快方块下落速度SpeedUp();break;case VK_DOWN: /按键。if( GetState()

42、= ST_PLAY ) /如果是游戏状态,方块加速下落Drop();break;case VK_UP: /按键。if( GetState() = ST_PLAY ) /如果是游戏状态,方块逆时针旋转90度Move( 3 );break;case A: /按A键。if( GetState() = ST_PRE )/如果是未开始或结束状态,开始游戏StartGame();break;case P: /按P键。if( GetState() = ST_PLAY ) /如果是游戏状态,暂停游戏PauseGame();elseResumeGame();/如果是暂停状态,继续游戏break;case R:

43、/按R键。if( GetState() = ST_PLAY ) /如果是游戏状态,重新开始游戏StartGame();break;case 1: /按1键。case 2: /按2键。case 3: /按3键。case 4: /按4键。case 5: /按5键。case 6: /按6键。case 7: /按7键。if( GetState() = ST_PLAY ) /如果是游戏状态,在提示窗口显示数字所对应的方块,即可自行控制下一个即将下落的方块SetShape( (char)pMsg-wParam - 1 );break;case N: /按N键。SpeedDown();/降低游戏级别,减慢方

44、块下落速度break;case M: /按M键。SpeedUp();/提高游戏级别,加快方块下落速度break;return true;return CDialog:PreTranslateMessage(pMsg);/=/开始游戏/=void CTetrisDlg:StartGame()/逐行扫描面板中的每一方格for( int nRowIndex = 0; nRowIndex ROW; nRowIndex + )/逐列扫描面板中的每一方格for( int nColIndex = 0; nColIndex = 0; nRow - )/逐列扫描面板中的每一方格for( nCol = 0; nC

45、ol COL; nCol+ )if( !m_DatanRownCol )/如果面板中该方格为空,则随机产生一种颜色clr = RGB( rand()%256, rand()%256, rand()%256 );else/如果面板中该方格非空,则获取面板该方格的颜色clr = m_clrDatanRownCol;/在该方格处以clr颜色值绘制方格,实现在空白处的填充效果 CPiece:DrawCell( &dc, CPoint( nCol, nRow ), clr, m_rctDisplay );_sleep( 10 );/延迟10毫秒/在溢满填充后,再逐行擦除已填充的方格,恢复到空白的面板状态

46、for( nRow = 0; nRow ROW; nRow + )DrawRow( &dc, nRow, true );_sleep( 50 ); /延迟50毫秒/-/清空面板所对应的m_Data数据for( int nRowIndex = 0; nRowIndex ROW; nRowIndex + )for( int nColIndex = 0; nColIndex COL; nColIndex + )m_DatanRowIndexnColIndex = false;m_nScores = 0;/分数归零m_nLevel = 0; /等级归零m_nState = ST_PRE;/状态恢复到非

47、开始或结束状态Invalidate();/绘制空白的面板/=/当前方块开始下落/=void CTetrisDlg:StartDrop( CDC *pDC )m_Piece = m_NextPiece;/待落方块转为下落方块m_Piece.m_ptCurPosition = CPoint( COL / 2 - 1, 0 );/下落位置为面板顶部中央m_NextPiece.DrawPiece( pDC, m_rctDisplay, true );/以背景颜色擦除待落方块m_NextPiece.NewPiece();/产生新的待落方块m_NextPiece.DrawPiece( pDC, m_rct

48、Display );/绘制新的待落方块if( MoveValid( m_Piece ) )/有效性检测/如果未越界并且未与已落方块重叠,则正常下落m_Piece.DrawPiece( pDC, m_rctDisplay ); /绘制下落方块SetTimer( 1, m_nElapse, NULL); /以m_nElapse为时间间隔设定定时器else/方块下落伊始如果越界或与已落方块重叠,则游戏结束KillTimer( 1 ); /删除定时器AbortGame();/结束游戏/=/当前方块下落/=void CTetrisDlg:Drop()CClientDCdc( this ); /声明新的设

49、备环境if( !Move( 2 ) )/ 如果下落失败FinishDrop( &dc );/停止下落/=/当前方块结束下落/=void CTetrisDlg:FinishDrop( CDC *pDC )/-/将下落方块绘入到已下落方块中去CPointptLocal;/逐行扫描方块中的每一方格for( int nRow = 0; nRow CELLROW; nRow + )/逐列扫描方块中的每一方格for( int nCol = 0; nCol CELLCOL; nCol + )/计算方块中的每一方格相对于面板的坐标ptLocal.x = m_Piece.m_ptCurPosition.x +

50、nCol;ptLocal.y = m_Piece.m_ptCurPosition.y + nRow;if( m_Piece.m_nDatanRownCol )/如果该方块中对应一个前景方格,则相应的面板方格置为非空(真),颜色设为当前下落方块的颜色m_DataptLocal.yptLocal.x = true;m_clrDataptLocal.yptLocal.x = m_Piece.m_clrData;/-/清行ClearRow( m_Piece.m_ptCurPosition.y, m_Piece.m_ptCurPosition.y + CELLROW );/-/显示积分和等级CStrin

51、gstr;str.Format( 分数:%d, m_nScores );SetDlgItemText(IDC_SCORE_STATIC, str );str.Format( 等级:%d, m_nLevel );SetDlgItemText(IDC_LEVEL_STATIC, str );/-/开始新的一个方块下落StartDrop( pDC );/=/方块的移动。/ int nMode:移动的方式,0:左移;1:右移;2:下落;3:逆时针旋转90度/=bool CTetrisDlg:Move( int nMode )CClientDCdc(this);/获取设备环境CPiecesp( m_Pi

52、ece );/构造CPiece对象实例switch( nMode )case 0:/ 若m_Piece=0,方块左移sp.m_ptCurPosition.x = m_Piece.m_ptCurPosition.x - 1;/当前位置x坐标减1,方块左移if( MoveValid( sp ) ) /判断左移后的方块是否超出面板显示区域/如果方块未超出面板显示区域m_Piece.DrawPiece( &dc, m_rctDisplay, true );/在当前位置上擦除方块m_Piece.m_ptCurPosition.x = sp.m_ptCurPosition.x;/获取新位置的坐标m_Pie

53、ce.DrawPiece( &dc, m_rctDisplay );/在新位置上绘制方块return true;break;case 1:/若m_Piece=1,方块右移sp.m_ptCurPosition.x = m_Piece.m_ptCurPosition.x + 1; /当前位置x坐标加1,方块右移if( MoveValid( sp ) ) /判断右移后的方块是否超出面板显示区域/如果方块未超出面板显示区域m_Piece.DrawPiece( &dc, m_rctDisplay, true ); /在当前位置上擦除方块m_Piece.m_ptCurPosition.x = sp.m_p

54、tCurPosition.x; /获取新位置的坐标m_Piece.DrawPiece( &dc, m_rctDisplay ); /在新位置上绘制方块return true;break;case 2:/若m_Piece=2,方块下落sp.m_ptCurPosition.y = m_Piece.m_ptCurPosition.y + 1; /当前位置y坐标加1,方块下移if( MoveValid( sp ) ) /判断右移后的方块是否超出面板显示区域/如果方块未超出面板显示区域m_Piece.DrawPiece( &dc, m_rctDisplay, true ); /在当前位置上擦除方块m_P

55、iece.m_ptCurPosition.y = sp.m_ptCurPosition.y; /获取新位置的坐标m_Piece.DrawPiece( &dc, m_rctDisplay ); /在新位置上绘制方块return true;break;case 3:/若m_Piece=3,方块逆时针旋转90度sp.m_nDirection = ( m_Piece.m_nDirection + 1 ) % DIRECTION;/当前方向发生变化,逆时针旋转90度if( MoveValid( sp ) )/有效性检测m_Piece.DrawPiece( &dc, m_rctDisplay, true

56、); /在当前位置上擦除方块m_Piece.m_nDirection = sp.m_nDirection; /获取当前位置的新方向m_Piece.InitData();/对方块重新初始化m_Piece.DrawPiece( &dc, m_rctDisplay );/ 在新方向上绘制方块return true;break;return false;/=/检测方块位置是否有效,包括越界检测和与已落方块重叠检测。/ CPiece sp:判断方块sp的位置是否有效/=bool CTetrisDlg:MoveValid( CPiece sp )CPointptLocal;/逐行扫描方块中的每一方格for

57、( int nRow = 0; nRow CELLROW; nRow + )/逐列扫描方块中的每一方格for( int nCol = 0; nCol CELLCOL; nCol + )/计算方块中的每一方格相对于面板的坐标ptLocal.x = sp.m_ptCurPosition.x + nCol;ptLocal.y = sp.m_ptCurPosition.y + nRow;/如果俄罗斯方块在旋转后移出面板之外,则返回假if( sp.m_nDatanRownCol & (ptLocal.x = COL | ptLocal.y = ROW ) )return false;/如果俄罗斯方块在旋

58、转后与面板中已有的方块相重叠,则返回假if( sp.m_nDatanRownCol & m_DataptLocal.yptLocal.x )return false;return true;/=/绘制面板中的一行。/ CDC *pDC:设备环境类 / int nRow:指定待绘制的行号/ bool bErase:是否擦除? bErase = true 则以背景色擦除该行/=void CTetrisDlg:DrawRow( CDC *pDC, int nRow, bool bErase/*=false*/ )for( int nCol = 0; nCol ROW - 1 )/如果扫描终止行超出面板总行数,则扫描终止行设为面板的最后一行。nBotton = ROW - 1;intnIndex, nRow, nCol;CUIntArrayanRow;/声明无符号整型数组,用以保存

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论