c++圖形學(xué)實(shí)驗(yàn)教程:游戲程序?qū)嵗ㄗ罱K稿)_第1頁
c++圖形學(xué)實(shí)驗(yàn)教程:游戲程序?qū)嵗ㄗ罱K稿)_第2頁
c++圖形學(xué)實(shí)驗(yàn)教程:游戲程序?qū)嵗ㄗ罱K稿)_第3頁
c++圖形學(xué)實(shí)驗(yàn)教程:游戲程序?qū)嵗ㄗ罱K稿)_第4頁
c++圖形學(xué)實(shí)驗(yàn)教程:游戲程序?qū)嵗ㄗ罱K稿)_第5頁
已閱讀5頁,還剩25頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、游戲程序?qū)嵗岸砹_斯方塊”是大家熟知的一款小游戲。本章將以“俄羅斯方塊”為實(shí)例講解如何利用C+語言開發(fā)平臺(tái)編寫Windows游戲。之所以選擇以“俄羅斯方塊”為例,就在于它簡單、易讀、易實(shí)現(xiàn)。當(dāng)讀者讀完本章時(shí),將能親手完成游戲程序的編寫,在理解游戲編寫細(xì)節(jié)的同時(shí),也能體會(huì)游戲開發(fā)的樂趣?!岸砹_斯方塊”游戲的玩法簡單易學(xué)。運(yùn)行游戲程序以后,首先用左右方向鍵或“M”、“N”鍵設(shè)置游戲的等級。右方向鍵或“M”鍵是等級提升1級,左方向鍵或“N”鍵是等級降低1級。設(shè)置好玩家需要的等級以后,單擊“開始”按鈕或按“A”鍵,這個(gè)時(shí)候方塊開始下落。在游戲的過程中,左、右方向鍵控制方塊的左、右移動(dòng);向下的方向鍵是使

2、方塊直接下落到底部;向上的方向鍵控制方塊的逆時(shí)針旋轉(zhuǎn),每按一次向上的方向鍵逆時(shí)針旋轉(zhuǎn)90度。在游戲的過程中,如果玩家不想游戲,想休息一下的話,可以單擊“暫?!卑粹o或按“P”鍵,這個(gè)時(shí)候,游戲就會(huì)暫時(shí)停止。當(dāng)玩家再次單擊“暫停”或再次按“P”鍵的時(shí)候,游戲又會(huì)繼續(xù)運(yùn)行。需要說明的是,如果玩家在游戲的過程中,覺得當(dāng)前的游戲等級不是很滿意,可以在游戲中進(jìn)行等級的更改設(shè)置。方法是游戲中用左、右兩個(gè)方向鍵或“M”、“N”鍵更改游戲的等級。游戲方法可總結(jié)為 REF _Ref200770342 h * MERGEFORMAT 表 1。表 SEQ 表 * ARABIC 1 游戲方法操作功能按“A”鍵或“開始”

3、按鈕開始游戲按“P”鍵或“暫?!卑粹o暫停/繼續(xù)游戲按“R”鍵重新開始游戲按“N”鍵方塊減速下落按“M”鍵方塊加速下落按“”鍵游戲狀態(tài),方塊左移;其它狀態(tài),減速按“”鍵游戲狀態(tài),方塊右移;其它狀態(tài),加速按“”鍵下落按“”鍵逆時(shí)針旋轉(zhuǎn)90度為說明方便,將本章內(nèi)出現(xiàn)的俄羅斯方塊游戲中各部分的名稱分別在 REF _Ref200770446 h 圖 1和 REF _Ref200770448 h 圖 2中標(biāo)出。圖 SEQ 圖 * ARABIC 1 名稱說明1圖 SEQ 圖 * ARABIC 2 名稱說明2第一節(jié) 程序構(gòu)建過程首先打開Microsoft Visual C+ 6.0。單擊“File”“New”

4、。這個(gè)時(shí)候就會(huì)出現(xiàn)“New”對話框。在“New”對話框中,選擇“Projects”表單。在“Projects”表單的列表框里選擇“MFC AppWizard(exe)”,然后在名稱里面輸入程序的名稱,“俄羅斯方塊”游戲程序的名稱是“Tetris”。然后在“Location”里面輸入保存的路徑。整個(gè)過程如 REF _Ref200770534 h 圖 3所示。圖 SEQ 圖 * ARABIC 3 創(chuàng)建新工程然后單擊“確定”,這個(gè)時(shí)候會(huì)出現(xiàn)“MFC AppWizard”對話框,選擇“Dialog based”,即“俄羅斯方塊”游戲程序是建立在對話框界面上的。如 REF _Ref200770642 h

5、 圖 4所示。圖 SEQ 圖 * ARABIC 4 創(chuàng)建基于對話框的界面然后點(diǎn)擊“Finish”按鈕,系統(tǒng)會(huì)彈出一個(gè)對話框,列出了用戶在創(chuàng)建工程時(shí)的一些預(yù)選信息。點(diǎn)擊“OK”后,就會(huì)生成相應(yīng)的程序包。當(dāng)完成以上的操作以后,程序會(huì)自動(dòng)生成一個(gè)工程,包括一個(gè)對話框界面。編譯之后,如 REF _Ref200770731 h 圖 5所示。圖 SEQ 圖 * ARABIC 5 創(chuàng)建后自動(dòng)生成的對話框接下來,就需要布置一下游戲的界面。在“Workspace”子窗口中,選擇 “Dialog”資源,在展開的樹形結(jié)構(gòu)中點(diǎn)擊相應(yīng)的對話框IDD_TETRIS_DIALOG,在右側(cè)窗口中便顯示出相應(yīng)的對話框編輯器。布

6、置控件的方法需要使用控件面板,如 REF _Ref200770803 h 圖 6所示。圖 SEQ 圖 * ARABIC 6 對話框資源編輯界面只要用鼠標(biāo)單擊控件,然后拖到圖形面板上相應(yīng)的位置就可以了。首先要?jiǎng)h除對話框中的所有控件,并增加如下控件。各個(gè)控件的主要屬性如下:控件ButtonIDIDC_STARTCaption開始控件ButtonIDIDC_PAUSECaption暫??丶﨎uttonIDIDC_ABORTCaption結(jié)束控件ButtonIDIDC_ABOUTCaption幫助控件ButtonIDIDC_EXITCaption退出控件TextIDIDC_SCORE_STATICCa

7、ption分?jǐn)?shù)控件TextIDIDC_LEVEL_STATICCaption等級布置好的界面如 REF _Ref200770862 h 圖 7所示。圖 SEQ 圖 * ARABIC 7 對話框編輯后的界面設(shè)置好以后,就要實(shí)現(xiàn)程序的代碼部分。第二節(jié) 源代碼注釋首先對全局常量進(jìn)行聲明。#defineSHAPE( 7 )/方塊的種類為7種,形狀分別為:圖 SEQ 圖 * ARABIC 8 俄羅斯方塊的形狀#defineDIRECTION( 4 )/方塊的方向,即每一種方塊四個(gè)方向。例如: 方向1 方向2 方向3 方向4圖 SEQ 圖 * ARABIC 9 俄羅斯方塊的方向#defineCELLROW

8、( 4 )/方塊格的行數(shù)#defineCELLCOL( 4 )/方塊格的列數(shù)44的方塊格可以完全包括所有類型的方塊。一個(gè)方塊由四個(gè)方格按不同位置組成,最長的是這種形狀,圖 SEQ 圖 * ARABIC 10 最長(高)的俄羅斯方塊因此在44的方塊格中可以表示任意形狀和方向的方塊。#defineROW( 24 )/面板格子的行數(shù)#defineCOL( 12 )/面板格子的列數(shù)面板是方塊下落和堆積的區(qū)域。#defineLEN( 18 )/每個(gè)方塊格的邊長為18個(gè)像素。接下來,定義一個(gè)名為CPiece的類,由該類來負(fù)責(zé)繪制每片方塊。顯然,有關(guān)方塊的形狀、方向、顏色等信息將出現(xiàn)在該類中;同時(shí),將由該類

9、的成員函數(shù)負(fù)責(zé)完成單片方塊的繪制工作。完整的類定義為:class CPiece : public CObject public:CPiece();/構(gòu)造函數(shù)virtual CPiece();/析構(gòu)函數(shù)CPiece( const CPiece &sp ); /重載構(gòu)造函數(shù)operator=( const CPiece &sp ); /重載賦值運(yùn)算public:voidInitData();/對方塊數(shù)據(jù)初始化voidNewPiece();/產(chǎn)生新的方塊數(shù)據(jù)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;/方塊的當(dāng)前位置intm_nDataCELLROWCELLCOL;/下落方塊的數(shù)據(jù)COLORREF m_clrData;/方塊的顏色信息friend class CTetrisDlg;CPiece類中有5個(gè)私有成員變量:變量m_

11、nShape保存的是方塊的形狀,其合法值為06;變量m_nDirection保存的是方塊的方向,其合法值為03;變量m_ptCurPosition保存的是方塊左上角在面板中的位置,由它來記錄方塊的下落路徑;數(shù)組m_nData保存的是下落方塊的數(shù)據(jù);變量m_clrData保存的是方塊的顏色。請注意,CTetrisDlg類是CPiece類的友元,這就意味著,CPiece類可以訪問CTetrisDlg類中的私有成員,這為兩類之間的數(shù)據(jù)交換提供了方便。CPiece()和CPiece( const CPiece &sp )是CPiece類的兩個(gè)構(gòu)造函數(shù),分別定義如下:/=/構(gòu)造函數(shù):/形狀為無效(-1)

12、;/ 方向?yàn)闊o效(-1);/ 位置為上部居中。/=CPiece:CPiece()/形狀變量初始化為-1,06為合法值。m_nShape= -1;/方向變量初始化為-1,03為合法值。m_nDirection= -1;/方塊下落的初始位置為面板頂部中間位置。m_ptCurPosition= CPoint( COL / 2 - 2, 0 ); /=/復(fù)制構(gòu)造函數(shù):/const CPiece &sp:為原方塊/=CPiece:CPiece( const CPiece &sp )/復(fù)制m_nShape成員變量(方塊的形狀);m_nShape= sp.m_nShape;/復(fù)制m_nDirection成員

13、變量(方塊的方向);m_nDirection= sp.m_nDirection;/復(fù)制m_ptCurPosition成員變量(方塊左上角的當(dāng)前位置);m_ptCurPosition= sp.m_ptCurPosition;/數(shù)據(jù)初始化;InitData();/復(fù)制m_clrData成員變量(方塊的顏色);m_clrData= sp.m_clrData;在CPiece類中,還有一個(gè)重載的賦值運(yùn)算,其函數(shù)與復(fù)制構(gòu)造函數(shù)完全一樣。在定義了重載的賦值運(yùn)算之后,就可以方便地初始化或修改一個(gè)CPiece實(shí)例了。/=/重載賦值運(yùn)算:/ const CPiece &sp 為原方塊/=CPiece:operat

14、or =(const CPiece &sp )/復(fù)制m_nShape成員變量(方塊的形狀);m_nShape= sp.m_nShape;/復(fù)制m_nDirection成員變量(方塊的方向);m_nDirection= sp.m_nDirection;/復(fù)制m_ptCurPosition成員變量(方塊左上角的當(dāng)前位置);m_ptCurPosition= sp.m_ptCurPosition;/數(shù)據(jù)初始化;InitData();/復(fù)制m_clrData成員變量(方塊的顏色);m_clrData = sp.m_clrData;在CPiece類中,4個(gè)私有成員函數(shù)。說明如下。InitData()函數(shù)是

15、對成員數(shù)組m_nDataCELLROWCELLCOL進(jìn)行初始化的函數(shù)。在該數(shù)組中保存的是即將下落的方塊的數(shù)據(jù)。/=/初始化形狀數(shù)據(jù)/保存在3 3的9個(gè)比特位中/=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保存的是即將下落的方塊的數(shù)據(jù)。/將Data保存到m_nData中,在Data保存的1位數(shù)據(jù)在轉(zhuǎn)換到m_nData中變?yōu)?個(gè)字節(jié)的數(shù)據(jù)。int nShift = CELLROW * CELLCOL - 1;for(int i = 0; i CELLROW; i+)for(int j = 0; j CELLCOL; j+)/通過右移,將Data保存的1位數(shù)據(jù)變?yōu)閙_nData中的1個(gè)字節(jié)的數(shù)據(jù)。轉(zhuǎn)換的數(shù)據(jù)按Data中由高到低的位順序進(jìn)行,因此右移位數(shù)的值nShift由大到小

19、變化。m_nDataij = (Data & (1 nShift; nShift-;/=/新建一個(gè)方塊/ 初始化方塊的形狀,/ 初始化方塊的方向,/ 初始化方塊的當(dāng)前位置,/ 初始化方塊的顏色,/ 對所有可能的形狀和方向數(shù)據(jù)初始化。/=void CPiece:NewPiece()m_nShape= rand() % SHAPE;/ 方塊的形狀數(shù)據(jù)隨機(jī)產(chǎn)生。m_nDirection= rand() % DIRECTION; / 方塊的方向數(shù)據(jù)隨機(jī)產(chǎn)生。m_ptCurPosition= CPoint( COL + 1, 1 ); / 方塊的當(dāng)前位置設(shè)定在提示區(qū)域。m_clrData= RGB( r

20、and()%255,rand()%255,rand()%255 ); / 方塊的顏色數(shù)據(jù)隨機(jī)產(chǎn)生。InitData();/對m_nData數(shù)組中的數(shù)據(jù)進(jìn)行初始化。/=/繪制方塊中的一個(gè)方格;/CDC *pDC:設(shè)備環(huán)境類指針;/ 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坐標(biāo)(以方塊為單位)nRow = ptLocal.y; /保存方塊左上角在面板中位置的y坐標(biāo)(以方塊為單位)ptTL.x= windowRect.left + nCol * LEN;/ 保存方塊左上角在用戶區(qū)域中位置的x坐標(biāo)(以像素為單位)ptTL.y= windowRect.top + nRow * LEN;/ 保存方塊左上角在用戶區(qū)域中位置的y坐標(biāo)(以像素為單位)ptBR.x= pt

22、TL.x + LEN; / 保存方塊右下角在用戶區(qū)域中位置的x坐標(biāo)(以像素為單位)ptBR.y= ptTL.y + LEN; / 保存方塊右下角在用戶區(qū)域中位置的y坐標(biāo)(以像素為單位)CRectrtCell( ptTL, ptBR );/ rtCell中保存的是填充矩形的坐標(biāo)。if( bErase )/如果擦除方格,則以系統(tǒng)顏色(即背景顏色)填充方格pDC-FillRect( &rtCell, &CBrush(GetSysColor(COLOR_3DFACE) );else/如果畫新的方格,方格內(nèi)部以參數(shù)clr所指定的顏色加以填充;/方格四邊留有1像素寬的邊框,/左邊框和上邊框涂白色;右邊框和

23、下邊框涂灰色,以顯示立體效果。/留出邊框位置(1個(gè)像素寬)ptTL.x +;ptTL.y +;ptBR.x -;ptBR.y -;/設(shè)置方格內(nèi)部區(qū)域?qū)?yīng)的矩形rtCell.SetRect( ptTL, ptBR );/以參數(shù)clr所指定的顏色,填充方格內(nèi)部區(qū)域?qū)?yīng)的矩形pDC-FillRect( &rtCell, &CBrush( clr ) );/創(chuàng)建白色畫筆CPenpnWhite( PS_SOLID, 1, RGB(255,255,255) );/創(chuàng)建灰色畫筆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 );/恢復(fù)原先的畫筆pDC-SelectObject( pOld );/釋放畫筆資源pnGray.DeleteObject();pn

25、White.DeleteObject();/=/繪制一個(gè)方塊 /CDC *pDC:設(shè)備環(huán)境類指針;/CRect windowRect:繪制窗口;/ bool bErase:是否擦除? bErase = true 則以背景色擦除該方塊/=void CPiece:DrawPiece( CDC *pDC, CRect windowRect, bool bErase/*= false*/ )CPointptLocal;/循環(huán)遍歷方塊中所有的方格位置for( int nRow = 0; nRow CELLROW; nRow + )for( int nCol = 0; nCol CELLCOL; nCol

26、 + )/計(jì)算方塊中每一方格的位置坐標(biāo)(以方格為單位)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類是工程創(chuàng)建過程中生成的類,它主要負(fù)責(zé)對話框的顯示和交互。俄羅斯方塊游戲的主要功能將在CTetrisDlg類中加以完成。首先看一下CTetrisDlg類的定義,然后對類中的成員變量和成員函數(shù)分別加以說明。#defineST_PRE( 0 )/游戲狀態(tài),0:游戲未開始或游戲結(jié)束狀態(tài)。#defineST_PLAY( 1 )/游戲狀態(tài),1:游戲進(jìn)行狀態(tài)。#defineST_PAUSE( 2 )/游戲狀態(tài),2:游戲暫停狀態(tài)。#defineTOPMARGIN( 12 )/游戲區(qū)域相對于用戶區(qū)域的上邊

28、距#defineLEFTMARGIN( 12 )/游戲區(qū)域相對于用戶區(qū)域的左邊距#defineLEVELMAX( 10 )/游戲最高等級數(shù)#defineDELAYPERLEVEL ( 80 )/速度參數(shù),即方塊移動(dòng)的時(shí)間間隔變化幅度(以毫秒計(jì))#defineSCOREPERLEVEL ( 50 )/游戲晉級的分?jǐn)?shù)間隔,即每增加多少分,游戲升高一級#defineELAPSEMAX( 1000 )/初始速度參數(shù),即游戲開始時(shí)方塊移動(dòng)的時(shí)間間隔(以毫秒計(jì))#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);/ 消息的預(yù)處理。protected:virtual void

30、 DoDataExchange(CDataExchange* pDX);/ DDX/DDV support/AFX_VIRTUALpublic:voidStartGame();/開始游戲voidPauseGame();/暫停游戲voidResumeGame();/繼續(xù)游戲voidAbortGame();/結(jié)束游戲voidStartDrop( CDC *pDC );/當(dāng)前方塊開始下落voidDrop();/當(dāng)前方塊下落voidFinishDrop( CDC *pDC );/當(dāng)前方塊結(jié)束下落boolMove( int nMode );/ 方塊的移動(dòng)。boolMoveValid( CPiece sp

31、 ); /檢測方塊位置是否有效,包括越界檢測和與已落方塊重疊檢測。voidDrawRow( CDC *pDC, int nRow, bool bErase = false );/繪制面板中的一行。voidClearRow( int nTop, int nBotton );/滿行時(shí),清行voidFlashRow( CDC *pDC, CUIntArray &anRow );/被清掉的行的閃爍intGetState();/獲得游戲狀態(tài)voidSetShape( int nID );/設(shè)置方塊的形狀,即用數(shù)字鍵人為控制待落方塊的形狀voidSpeedUp();/加速下落voidSpeedDown()

32、;/減速下落private:intm_nScores;/游戲分?jǐn)?shù)intm_nElapse;/方塊移動(dòng)的時(shí)間間隔(以毫秒計(jì))intm_nLevel;/游戲等級(010級)intm_nState;/游戲狀態(tài)(0:游戲未開始或游戲結(jié)束;1:游戲進(jìn)行;2:游戲暫停;)CPiecem_Piece;/下落的俄羅斯方塊的形狀;CPiecem_NextPiece; /下一片俄羅斯方塊的形狀;boolm_DataROWCOL;/面板中方格數(shù)據(jù),true代表有方塊;false代表無方塊。COLORREFm_clrDataROWCOL;/ 面板中方格顏色數(shù)據(jù)CRectm_rctDisplay;/面板顯示區(qū)域/ Im

33、plementationprotected:HICON m_hIcon;/ Generated message map functions/AFX_MSG(CTetrisDlg)virtual BOOL OnInitDialog();/ 對話框初始化。afx_msg void OnPaint();/ 繪圖消息響應(yīng)函數(shù)。afx_msg void OnAbout();/ 按幫助按鈕的消息響應(yīng)函數(shù),彈出About對話框。afx_msg void OnStart();/ 按開始按鈕的消息響應(yīng)函數(shù),開始游戲。afx_msg void OnPause();/ 按暫停按鈕的消息響應(yīng)函數(shù),暫停游戲或繼續(xù)游戲。

34、afx_msg void OnAbort();/ 按結(jié)束按鈕的消息響應(yīng)函數(shù),結(jié)束游戲。afx_msg void OnTimer(UINT nIDEvent);/ 定時(shí)器消息響應(yīng)函數(shù)。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) );/以系統(tǒng)時(shí)間為參數(shù)設(shè)定隨機(jī)種子。/將m_Data數(shù)組中的元素初始化為false,即整個(gè)面板在初始時(shí)無方塊。for( int nRowIndex = 0; nRowIndex ROW; nRowIndex + )for( int nColIndex = 0; nColIndex COL; nC

36、olIndex + )m_DatanRowIndexnColIndex = false;m_NextPiece.NewPiece();/產(chǎn)生一個(gè)新的方塊,保存于m_NextPiece.實(shí)例中。m_nScores= 0;/初始分?jǐn)?shù)為0。m_nLevel= 0;/初始等級為0。m_nElapse= ELAPSEMAX; /方塊移動(dòng)的時(shí)間間隔初始化為1000(以毫秒計(jì))m_nState= ST_PRE;/游戲狀態(tài)初始化為0,即游戲未開始或結(jié)束。m_rctDisplay = CRect(LEFTMARGIN,TOPMARGIN,LEFTMARGIN + COL * LEN,TOPMARGIN + RO

37、W * LEN);/面板顯示區(qū)域初始化,相對于用戶區(qū)域留有一定邊距。return TRUE; / return TRUE unless you set the focus to a control/=/ 繪圖消息響應(yīng)函數(shù)/=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);/聲明設(shè)備環(huán)境對象實(shí)例。CBrush*pOld = NULL;/聲明畫刷指針。pOld

39、 = (CBrush *)dc.SelectStockObject( NULL_BRUSH ); /選擇空畫刷,即在繪制封閉區(qū)域時(shí),不做任何顏色的填充。dc.Rectangle(m_rctDisplay.left - 1, m_rctDisplay.top - 1, m_rctDisplay.right + 1, m_rctDisplay.bottom + 1);/繪制面板顯示區(qū)域矩形,即方塊下落的游戲區(qū)域。dc.SelectObject( pOld );/恢復(fù)原來的畫筆/顯示游戲分?jǐn)?shù)和游戲等級CStringstr;str.Format( 分?jǐn)?shù):%d, m_nScores );SetDlgIt

40、emText(IDC_SCORE_STATIC, str ); /顯示游戲分?jǐn)?shù)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);/=/ 消息的預(yù)處理,這里主要處理按鍵消息/=BOOL CTetrisDlg:PreTranslateMessage(MSG* pMsg) if( pMsg-

41、message = WM_KEYDOWN )/處理按鍵消息switch( pMsg-wParam )case VK_LEFT:/按鍵。if( GetState() = ST_PLAY )/如果是游戲狀態(tài),方塊左移Move( 0 );else /否則,降低游戲級別,減慢方塊下落速度SpeedDown();break;case VK_RIGHT: /按鍵。if( GetState() = ST_PLAY ) /如果是游戲狀態(tài),方塊右移Move( 1 );else /否則,提高游戲級別,加快方塊下落速度SpeedUp();break;case VK_DOWN: /按鍵。if( GetState()

42、= ST_PLAY ) /如果是游戲狀態(tài),方塊加速下落Drop();break;case VK_UP: /按鍵。if( GetState() = ST_PLAY ) /如果是游戲狀態(tài),方塊逆時(shí)針旋轉(zhuǎn)90度Move( 3 );break;case A: /按A鍵。if( GetState() = ST_PRE )/如果是未開始或結(jié)束狀態(tài),開始游戲StartGame();break;case P: /按P鍵。if( GetState() = ST_PLAY ) /如果是游戲狀態(tài),暫停游戲PauseGame();elseResumeGame();/如果是暫停狀態(tài),繼續(xù)游戲break;case R:

43、/按R鍵。if( GetState() = ST_PLAY ) /如果是游戲狀態(tài),重新開始游戲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 ) /如果是游戲狀態(tài),在提示窗口顯示數(shù)字所對應(yīng)的方塊,即可自行控制下一個(gè)即將下落的方塊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 )/如果面板中該方格為空,則隨機(jī)產(chǎn)生一種顏色clr = RGB( rand()%256, rand()%256, rand()%256 );else/如果面板中該方格非空,則獲取面板該方格的顏色clr = m_clrDatanRownCol;/在該方格處以clr顏色值繪制方格,實(shí)現(xiàn)在空白處的填充效果 CPiece:DrawCell( &dc, CPoint( nCol, nRow ), clr, m_rctDisplay );_sleep( 10 );/延遲10毫秒/在溢滿填充后,再逐行擦除已填充的方格,恢復(fù)到空白的面板狀態(tài)

46、for( nRow = 0; nRow ROW; nRow + )DrawRow( &dc, nRow, true );_sleep( 50 ); /延遲50毫秒/-/清空面板所對應(yīng)的m_Data數(shù)據(jù)for( int nRowIndex = 0; nRowIndex ROW; nRowIndex + )for( int nColIndex = 0; nColIndex COL; nColIndex + )m_DatanRowIndexnColIndex = false;m_nScores = 0;/分?jǐn)?shù)歸零m_nLevel = 0; /等級歸零m_nState = ST_PRE;/狀態(tài)恢復(fù)到非

47、開始或結(jié)束狀態(tài)Invalidate();/繪制空白的面板/=/當(dāng)前方塊開始下落/=void CTetrisDlg:StartDrop( CDC *pDC )m_Piece = m_NextPiece;/待落方塊轉(zhuǎn)為下落方塊m_Piece.m_ptCurPosition = CPoint( COL / 2 - 1, 0 );/下落位置為面板頂部中央m_NextPiece.DrawPiece( pDC, m_rctDisplay, true );/以背景顏色擦除待落方塊m_NextPiece.NewPiece();/產(chǎn)生新的待落方塊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為時(shí)間間隔設(shè)定定時(shí)器else/方塊下落伊始如果越界或與已落方塊重疊,則游戲結(jié)束KillTimer( 1 ); /刪除定時(shí)器AbortGame();/結(jié)束游戲/=/當(dāng)前方塊下落/=void CTetrisDlg:Drop()CClientDCdc( this ); /聲明新的設(shè)

49、備環(huán)境if( !Move( 2 ) )/ 如果下落失敗FinishDrop( &dc );/停止下落/=/當(dāng)前方塊結(jié)束下落/=void CTetrisDlg:FinishDrop( CDC *pDC )/-/將下落方塊繪入到已下落方塊中去CPointptLocal;/逐行掃描方塊中的每一方格for( int nRow = 0; nRow CELLROW; nRow + )/逐列掃描方塊中的每一方格for( int nCol = 0; nCol CELLCOL; nCol + )/計(jì)算方塊中的每一方格相對于面板的坐標(biāo)ptLocal.x = m_Piece.m_ptCurPosition.x +

50、nCol;ptLocal.y = m_Piece.m_ptCurPosition.y + nRow;if( m_Piece.m_nDatanRownCol )/如果該方塊中對應(yīng)一個(gè)前景方格,則相應(yīng)的面板方格置為非空(真),顏色設(shè)為當(dāng)前下落方塊的顏色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( 分?jǐn)?shù):%d, m_nScores );SetDlgItemText(IDC_SCORE_STATIC, str );str.Format( 等級:%d, m_nLevel );SetDlgItemText(IDC_LEVEL_STATIC, str );/-/開始新的一個(gè)方塊下落StartDrop( pDC );/=/方塊的移動(dòng)。/ int nMode:移動(dòng)的方式,0:左移;1:右移;2:下落;3:逆時(shí)針旋轉(zhuǎn)90度/=bool CTetrisDlg:Move( int nMode )CClientDCdc(this);/獲取設(shè)備環(huán)境CPiecesp( m_Pi

52、ece );/構(gòu)造CPiece對象實(shí)例switch( nMode )case 0:/ 若m_Piece=0,方塊左移sp.m_ptCurPosition.x = m_Piece.m_ptCurPosition.x - 1;/當(dāng)前位置x坐標(biāo)減1,方塊左移if( MoveValid( sp ) ) /判斷左移后的方塊是否超出面板顯示區(qū)域/如果方塊未超出面板顯示區(qū)域m_Piece.DrawPiece( &dc, m_rctDisplay, true );/在當(dāng)前位置上擦除方塊m_Piece.m_ptCurPosition.x = sp.m_ptCurPosition.x;/獲取新位置的坐標(biāo)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; /當(dāng)前位置x坐標(biāo)加1,方塊右移if( MoveValid( sp ) ) /判斷右移后的方塊是否超出面板顯示區(qū)域/如果方塊未超出面板顯示區(qū)域m_Piece.DrawPiece( &dc, m_rctDisplay, true ); /在當(dāng)前位置上擦除方塊m_Piece.m_ptCurPosition.x = sp.m_p

54、tCurPosition.x; /獲取新位置的坐標(biāo)m_Piece.DrawPiece( &dc, m_rctDisplay ); /在新位置上繪制方塊return true;break;case 2:/若m_Piece=2,方塊下落sp.m_ptCurPosition.y = m_Piece.m_ptCurPosition.y + 1; /當(dāng)前位置y坐標(biāo)加1,方塊下移if( MoveValid( sp ) ) /判斷右移后的方塊是否超出面板顯示區(qū)域/如果方塊未超出面板顯示區(qū)域m_Piece.DrawPiece( &dc, m_rctDisplay, true ); /在當(dāng)前位置上擦除方塊m_P

55、iece.m_ptCurPosition.y = sp.m_ptCurPosition.y; /獲取新位置的坐標(biāo)m_Piece.DrawPiece( &dc, m_rctDisplay ); /在新位置上繪制方塊return true;break;case 3:/若m_Piece=3,方塊逆時(shí)針旋轉(zhuǎn)90度sp.m_nDirection = ( m_Piece.m_nDirection + 1 ) % DIRECTION;/當(dāng)前方向發(fā)生變化,逆時(shí)針旋轉(zhuǎn)90度if( MoveValid( sp ) )/有效性檢測m_Piece.DrawPiece( &dc, m_rctDisplay, true

56、); /在當(dāng)前位置上擦除方塊m_Piece.m_nDirection = sp.m_nDirection; /獲取當(dāng)前位置的新方向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 + )/計(jì)算方塊中的每一方格相對于面板的坐標(biāo)ptLocal.x = sp.m_ptCurPosition.x + nCol;ptLocal.y = sp.m_ptCurPosition.y + nRow;/如果俄羅斯方塊在旋轉(zhuǎn)后移出面板之外,則返回假if( sp.m_nDatanRownCol & (ptLocal.x = COL | ptLocal.y = ROW ) )return false;/如果俄羅斯方塊在旋

58、轉(zhuǎn)后與面板中已有的方塊相重疊,則返回假if( sp.m_nDatanRownCol & m_DataptLocal.yptLocal.x )return false;return true;/=/繪制面板中的一行。/ CDC *pDC:設(shè)備環(huán)境類 / int nRow:指定待繪制的行號/ bool bErase:是否擦除? bErase = true 則以背景色擦除該行/=void CTetrisDlg:DrawRow( CDC *pDC, int nRow, bool bErase/*=false*/ )for( int nCol = 0; nCol ROW - 1 )/如果掃描終止行超出面板總行數(shù),則掃描終止行設(shè)為面板的最后一行。nBotton = ROW - 1;intnIndex, nRow, nCol;CUIntArrayanRow;/聲明無符號整型數(shù)組,用以保存

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論