VC++_win32_API_游戲開發(fā)(最新).ppt_第1頁
VC++_win32_API_游戲開發(fā)(最新).ppt_第2頁
VC++_win32_API_游戲開發(fā)(最新).ppt_第3頁
VC++_win32_API_游戲開發(fā)(最新).ppt_第4頁
VC++_win32_API_游戲開發(fā)(最新).ppt_第5頁
已閱讀5頁,還剩69頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

VC+win32API游戲開發(fā),主講教師:李璟聯(lián)系電話-mail:lijing,VC+win32API游戲開發(fā),1.Windows編程2.Windows應用程序的組成與編程3.游戲實現原理與WindowGDI繪圖4.游戲實例的剖析,1.Windows編程,1.1WindowsAPI編程基礎1.2窗口1.3事件驅動1.4句柄1.5消息1.6Windows應用程序的常用消息,1.1WindowsAPI編程基礎,Windows編程的方法主要有兩種方法:傳統(tǒng)編寫法:利用API函數。交互式方法:利用MFC類庫。為使程序員編寫具有Windows風格的應用程序,Windows提供了一個應用程序編程接口(ApplicationProgrammingInterface,簡稱API),它是Windows系統(tǒng)與Windows應用程序間的標準程序接口。上千個API函數包含了各種窗口類和系統(tǒng)資源。API可以為應用程序提供windows系統(tǒng)特殊函數及數據結構。windows應用程序可以利用大量API函數調用系統(tǒng)功能。,MFC,MFC,MicrosoftFoundationClassLibrary,微軟基礎類庫,約有200個類。MFC封裝了大部分API函數,并提供了一個應用程序框架,簡化了和標準了windows程序設計。但WindowsAPI編程方法始終是windows編程的基礎。,1.2窗口,編寫一個Windows應用程序首先應創(chuàng)建一個或多個窗口,而后應用程序的運行過程即是窗口內部、窗口與窗口之間、窗口與系統(tǒng)之間進行數據處理與數據交換的過程。,1.3事件驅動,Windows程序設計是針對事件或消息的,它的執(zhí)行順序取決于事件發(fā)生的順序。在Windows環(huán)境下,應用程序啟動后,系統(tǒng)等待用戶在圖形用戶界面內的輸入選擇,如鼠標按鍵、鍵盤按鍵、窗口被創(chuàng)建、關閉、改變大小、移動等,對系統(tǒng)來說,這都是事件,都會產生相應的windows消息。事件驅動編程方法對于編寫交互式程序很有用處,它避免了死板的操作模式。,1.4句柄,句柄,顧名思義,指的是一個windows對象的把柄。Windows中的句柄都是32位的指針變量,用來指向某個windows對象所占據的內存區(qū)。句柄的使用,極大地方便了Windows管理其內存中的各種windows對象。,常用句柄類型及其說明,1.5消息,消息是描述事件發(fā)生的信息。Windows應用程序通過消息進行信息交換。在Windows中,消息用結構體MSG表示,其結構如下:TypedefstructtagMSGHWNDhwnd;/窗口句柄UNITmessage;/消息號。WPARAMwParam;/用于提供消息的附加消息。LPARAMlParam;/用于提供消息的附加消息。DWORDtime;/指定消息送至隊列的時間POINTpt;/指定消息發(fā)送時屏幕光標的位置MSG;,VC+中存在幾種系統(tǒng)定義的消息分類,不同的前綴符號經常用于識別消息的分類,如下表所示:,1.6Windows應用程序的常用消息,1.鼠標消息,主要有:WM_LBUTTONDOWN:產生單擊鼠標左鍵的消息。WM_LBUTTONUP:放開鼠標左鍵時產生的消息。2.鍵盤消息,主要有:WM_KEYDOWN:按下一個系統(tǒng)鍵時產生的消息。WM_KEYUP:放開一個系統(tǒng)鍵時產生的消息。3.窗口消息,主要有:WM_CREATE:窗口創(chuàng)建時,由CreateWindows函數發(fā)出的消息。WM_CLOSE:關閉窗口時產生的消息。WM_QUIT:退出應用程序時,由PostQuitMessage函數發(fā)出消息。,2.Windows應用程序的組成與編程,2.1典型的Windows程序結構2.2入口函數WinMain()2.3窗口函數WinProc()2.4windows應用程序的常用數據類型2.5API編程實例,2.1典型的Windows程序結構,Windows應用程序的主體由以下兩個函數完成:WinMain()函數負責建立窗口和建立消息循環(huán)。WinProc()函數負責消息的處理。,2.1典型的Windows程序結構,2.2入口函數WinMain(),WinMain()函數類似C語言中的Main函數,是Win32應用程序入口函數。WinMain()函數主要完成創(chuàng)建主窗口,并產生和處理消息循環(huán)。,WinMain()函數,因為windows是多任務系統(tǒng),所以同一應用程序的多個窗口可能會同時存在。windows系統(tǒng)對每個窗口的執(zhí)行稱為一個實例,用一個實例句柄來唯一標識。WinMain()函數與DOS程序的main()函數起同樣的作用,有一點不同的是,WinMain()函數必須帶有四個參數,它們是系統(tǒng)傳遞給它的。WinMain()函數的原型如下:intPASCALWinMain(HINSTANCEhInstance,/當前實例句柄HINSTANCEhPrevInstance,/前一個實例句柄LPSTRlpCmdLine,/命令行字符intnCmdShow)/窗口顯示方式,WinMain()函數,第一個參數hInstance,是標識該應用程序當前實例的句柄。第二個參數是hPrevInstance,它是用來標識該應用程序的前一個實例的句柄。第三個參數是lpCmdLine,是指向應用程序命令行參數字符串的指針。最后一個參數是nCmdShow,是一個用來指定窗口顯示方式的整數。這個整數值可以是SW_SHOW、SW_HIDE、SW_SHOWMAXIMIZED、SW_SHOWMINIMIZED等。,WinMain()函數主要由2部分組成:窗口初始化消息循環(huán),窗口初始化包括以下主要步驟:,定義窗口類:通過給窗口類數據結構WINDCLASS賦值,設置窗口類的各種屬性。如窗口邊框、窗口標題欄文字、窗口大小和位置、鼠標、背景色等。注冊窗口類:Win系統(tǒng)本身提供部分預定義的窗口類,程序員也可以自定義窗口類。窗口類必須先注冊后使用。窗口類的注冊由函數RegisterClass()實現。創(chuàng)建窗口實例:創(chuàng)建窗口類的實例由CreateWindows()函數實現。窗口顯示:窗口類的顯示是由ShowWindows()函數和UpdateWindows()函數實現的。ShowWindows()函數:應用程序通過調用ShowWindows()函數在屏幕上顯示窗口。UpdateWindows()函數:顯示窗口后,應用程序調用UpdateWindow更新并繪制用戶區(qū),并發(fā)出WM_PAINT消息。,消息循環(huán),Windows為當前執(zhí)行的每個Windows程序維護一個消息隊列。在發(fā)生輸入事件之后,Windows將事件轉換為一個消息并將消息放入程序的消息隊列中。程序通過執(zhí)行一塊稱之為消息循環(huán)的程序代碼從消息隊列中取出消息。以下是WinMain()函數中消息循環(huán)的代碼:/消息循環(huán)以調用GetMessage()開始,它從消息隊列中取出/一個消息while(GetMessage(,WinMain()函數的大致結構,intPASCALWinMain()/定義窗口類:WNDCLASSwndclass;wndclass.style=CS_HREDRAW|CS_VREDRAW;十個字段wndclass.lpszClassName=”Lei”;/注冊窗口類:RegisterClass(,2.3窗口函數WndProc(),窗口函數WndProc()就是Windows應用程序的消息處理程序。窗口函數WndProc()定義了應用程序對接收到的不同消息的響應,包含了對各種可能接收到的消息的處理過程。WndProc函數由一個或多個switch語句組成。每一條case語句對應一種消息,當應用程序接收到一個消息時,相應的case語句被激活并執(zhí)行相應的響應程序模塊。窗口消息處理程序不予處理的所有消息被傳給名為DefWindowProc的Windows函數進行默認處理。,消息處理函數WndProc的大致結構,LRESULTCALLBACKWndProc(HWNDhMainwnd,UINTmessage,WPARAMwParam,LPARAMlParam)/窗口函數的定義switch(message)caseWM_KEYDOWN:/擊鍵消息;break;case:;break;caseWM_DESTROY:/關閉應用程序窗口時發(fā)出的消息PostQuitMessage(0);/發(fā)出WM_QUIT消息,結束應用程序return0;default:break;/調用缺省消息處理過程returnDefWindowProc(hMainwnd,message,wParam,lParam);,2.4windows應用程序的常用數據類型,所有的Windows應用程序中,都有一個程序初始化的過程。下面以一個實現最簡單功能的程序WinApiDemo為例,說明Windows程序的基本框架。操作步驟如下:(1)打開VisualC+6.0。選擇File菜單的New,在出現的對話框中,選擇Projects欄目(新建工程),并點取其下的Win32Application項,表示使用Win32環(huán)境創(chuàng)建應用程序。(2)在Locatin(路徑)中填入工程的路徑,然后在ProjectName(項目名稱)中填入“WinApiDemo”,其它按照缺省設置,單擊OK按鈕。(3)選擇File菜單的New,在出現的對話框中,選擇Files欄目(新建文件),并點取其下的C+SourceFile項,表示新建一個C+源文件。在右邊的File欄中輸入“WinApiDemo”,最后確定讓Addtoproject檢查框打上勾,單擊OK按鈕。(4)在“WinApiDemo.cpp”文件中輸入以下程序代碼。,2.5API編程實例,WinApiDemo.cpp源代碼(1),#include/頭文件LRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);/窗口函數聲明,這一函數將處理發(fā)往應用程序窗口的各種消息charszClassName=windowclass;/窗口結構體的名稱charszAppTitle=API建立窗口實例;/窗口的標題INTPASCALWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPSTRlpszCmdParam,INTnCmdShow)/WinMain()函數的定義HWNDhMainWnd;/窗口句柄MSGmsg;/消息結構體WNDCLASSwinclass;/窗口結構體if(!hPrevInstance)winclass.style=CS_HREDRAW|CS_VREDRAW;/窗口風格winclass.lpfnWndProc=WndProc;winclass.cbClsExtra=0;/附加參數winclass.cbWndExtra=0;/附加參數winclass.hInstance=hInstance;/當前應用程序實例句柄winclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);/窗口圖標winclass.hCursor=LoadCursor(NULL,IDC_ARROW);/窗口光標winclass.hbrBackground=(HBRUSH)GetStockObject(LTGRAY_BRUSH);/窗口背景色為淺灰色winclass.lpszMenuName=NULL;/窗口菜單winclass.lpszClassName=szClassName;/給窗口結構體命名,/CreateWindow()函數將根據窗口結構體的名稱來建立窗口RegisterClass(/注冊窗口,WinApiDemo.cpp源代碼(2),/下面用CreateWindow()函數來建立窗口,并返回所建立窗口的句柄hMainWnd=CreateWindow(szClassName,/窗口結構體的名稱szAppTitle,/窗口的標題WS_OVERLAPPEDWINDOW,/窗口風格為可重疊窗口/下面四個參數代表窗口左上角x,y坐標和窗口的寬度與高度,都使/用缺省值CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,/下面參數分別為父窗口句柄、窗口菜單句柄、應用程序實例句柄/和附加參數NULL,NULL,hInstance,NULL);ShowWindow(hMainWnd,SW_SHOWNORMAL);/顯示最大化窗口UpdateWindow(hMainWnd);/更新窗口/下面用While()循環(huán)來建立消息循環(huán)while(GetMessage(,WinApiDemo.cpp源代碼(3),LRESULTCALLBACKWndProc(HWNDhMainwnd,UINTmessage,WPARAMwParam,LPARAMlParam)/窗口函數的定義switch(message)caseWM_KEYDOWN:/擊鍵消息MessageBox(hMainwnd,鍵按下了!,Keyboard,MB_OK);break;caseWM_RBUTTONDOWN:/鼠標消息MessageBox(hMainwnd,鼠標右鍵按下了!,Mouse,MB_OK);break;caseWM_LBUTTONDOWN:/鼠標消息MessageBox(hMainwnd,鼠標左鍵按下了!,Mouse,MB_OK);break;caseWM_DESTROY:/關閉應用程序窗口時發(fā)出的消息PostQuitMessage(0);/發(fā)出WM_QUIT消息,結束應用程序return0;default:break;/調用缺省消息處理過程returnDefWindowProc(hMainwnd,message,wParam,lParam);,WinApiDemo.cpp源代碼(4),caseWM_RBUTTONDOWN:MessageBox(GetFocus(),messageright,API建立窗口實例,MB_OK|MB_ICONINFORMATION);break;caseWM_LBUTTONDOWN:MessageBox(GetFocus(),messageleft,API建立窗口實例,MB_OK|MB_ICONINFORMATION);break;caseWM_DESTROY:/關閉應用程序窗口時發(fā)出的消息PostQuitMessage(0);/發(fā)出WM_QUIT消息,結束應用程序return0;default:break;returnDefWindowProc(hMainwnd,message,wParam,lParam);/其它沒有處理的消息交給Windows做默認處理,WinApiDemo的運行畫面,3.游戲實現原理與WindowGDI繪圖,3.1游戲實現的基本原理3.2WindowGDI基本概念3.3利用GDI實現游戲中的繪圖,3.1游戲實現的基本原理,3.2WindowGDI基本概念,GDI,GraphicsDeviceInterface,即圖形設備接口,是WindowsAPI的一個重要組成部分。GDI是Windows圖形顯示程序與實際物理設備之間的橋梁,GDI使得用戶無需關心具體設備的細節(jié),而只需在一個虛擬的環(huán)境(即邏輯設備)中進行操作。GDI用一套通用的圖形對象來向屏幕,內存甚至是打印機繪圖。,GDI函數大致可分類為:設備上下文函數:如GetDC、CreateDC、DeleteDC。畫線函數:如LineTo、Polyline、Arc。填充畫圖函數:如Ellipse、FillRect、Pie。畫圖屬性函數:如SetBkColor、SetBkMode、SetTextColor。文本、字體函數:如TextOut、GetFontData。位圖函數:如SetPixel、BitBlt、StretchBlt。坐標函數:如DPtoLP、LPtoDP、ScreenToClient、ClientToScreen。映射函數:如SetMapMode、SetWindowExtEx、SetViewportExtEx。元文件函數:如PlayMetaFile、SetWinMetaFileBits。區(qū)域函數:如FillRgn、FrameRgn、InvertRgn。路徑函數:如BeginPath、EndPath、StrokeAndFillPath。裁剪函數:如SelectClipRgn、SelectClipPath。,設備上下文,在GDI編程中,幾乎所有的操作都圍繞設備上下文(DC)展開。設備上下文,DeviceContext,簡稱DC,是Windows使用的一種結構,所有GDI操作前都需取得特定設備的上下文。設備上下文的句柄是HDC。HDC是一個你可以向其繪圖的句柄;它可以代表整個屏幕,一個窗口的客戶區(qū)域,一個存在內存中的位圖,或是一個打印機。例如,如果你想在一個窗口上繪圖,首先你要用GetDC()來獲取代表這個窗口的HDC,然后你就可以用任何以HDC為參數的GDI函數來繪圖了。,位圖,位圖可以用LoadBitmap()來完成大多數的基本操作,比如簡單地裝入一個位圖資源。GDI不能直接用位圖對象來繪圖,因為繪圖操作已經被設備上下文抽象了,只能通過設備上下文來繪制位圖。利用位圖繪圖的大體思路是:把位圖對象裝入設備上下文,通過設備上下文把位圖顯示在屏幕上。,3.3利用GDI實現游戲中的繪圖,游戲中的繪圖主要通過是繪制位圖來實現的。在游戲中,因為角色位圖的位置是不斷變化的,所以設備上下文中的合成位圖的內容也是不斷變化的。為了實現游戲畫面的刷新,通常是利用緩存設備上下文來保存下一幀的合成位圖對象。下一幀的合成位圖對象是根據角色位圖的實時位置和狀態(tài)重新渲染后的結果。,下面舉例給出了利用GDI實現位圖繪圖的主要步驟:定義windows屏幕設備句柄變量windowDC;定義窗口緩沖設備句柄變量bufferDC;定義一個位圖內存設備句柄變量picDC;定義一個位圖句柄變量picBMP;定義一個緩沖位圖句柄變量bufferBMP;調用GetDC()獲取當前整個屏幕設備的句柄值,賦給windowDC;調用CreateCompatibleDC()創(chuàng)建與windowDC兼容的內存設備,并將其句柄值賦給位圖內存設備變量picDC。調用CreateCompatibleDC()創(chuàng)建與windowDC兼容的內存設備,并其句柄值賦給窗口緩沖設備變量bufferDC。調用CreateCompatibleBitmap()創(chuàng)建與windowDC兼容的位圖對象,并將該位圖的句柄值賦給bufferBMP。調用LoadBitmap()加載指定位圖資源,并獲取給該位圖資源的句柄值,賦給picBMP。調用SelectObject()將緩沖位圖句柄bufferBMP和窗口緩沖設備句柄bufferDC關聯(lián)。調用SelectObject()將位圖句柄picBMP和位圖內存設備picDC關聯(lián)。兩次調用特定運算的BitBlt()函數來對位圖內存設備picDC中的位圖進行“去背”處理后,把結果保存在窗口緩沖設備bufferDC中。調用BitBlt()函數將窗口緩沖設備中的全部圖像內容拷貝到屏幕設備windowDC上顯示。,GetDC()函數,函數功能:該函數檢索一指定窗口的客戶區(qū)域或整個屏幕的顯示設備上下文環(huán)境的句柄,以后可以在GDI函數中使用該句柄來在設備上下文環(huán)境中繪圖。函數原型:HDCGetDC(HWNDhWnd);參數:hWnd:設備上下文環(huán)境被檢索的窗口的句柄,如果該值為NULL,GetDC則檢索整個屏幕的設備上下文環(huán)境。返回值:如果成功,返回指定窗口客戶區(qū)的設備上下文環(huán)境;如果失敗,返回值為Null。,CreateCompatibleDC()函數,函數功能:該函數創(chuàng)建一個與指定設備兼容的內存設備上下文環(huán)境(DC)。函數原型:HDCCreateCompatibleDC(HDChdc);參數:hdc:現有設備上下文環(huán)境的句柄,如果該句柄為NULL,該函數創(chuàng)建一個與應用程序的當前顯示器兼容的內存設備上下文環(huán)境。返回值:如果成功,則返回內存設備上下文環(huán)境的句柄;如果失敗,則返回值為NULL。,CreateCompatibleBitmap()函數,函數功能:該函數創(chuàng)建與指定的設備環(huán)境相關的設備兼容的位圖。函數原型:HBITMAPCreateCompatibleBitmap(HDChdc,intnWidth,intnHeight);參數:hdc:設備環(huán)境句柄。nWidth:指定位圖的寬度,單位為像素。nHeight:指定位圖的高度,單位為像素。返回值:如果函數執(zhí)行成功,那么返回值是位圖的位圖句柄;如果函數執(zhí)行失敗,那么返回值為NULL。,LoadBitmap()函數,函數功能:該函數從模塊的可執(zhí)行文件中加載指定的位圖資源。函數原型:HBITMAPLoadBitmap(HINSTANCEhInstance,LPCTSTRlpBitmapName);參數:hlnstance:指向模塊實例的句柄。lpBitmapName:指向字符串指針。該字符串包含了要加載的位圖資源名稱。返回值:如果函數執(zhí)行成功,則返回值是指向指定位圖的位圖句柄。如果函數執(zhí)行失敗,那么返回值是NULL。,SelectObject()函數,函數功能:該函數選擇一對象到指定的設備上下文環(huán)境中。函數原型:HGDIOBJSelectObject(HDChdc,HGDIOBJhgdiobj);參數:hdc:設備上下文環(huán)境的句柄。hgdiobj:被選擇的對象的句柄,這些對象包括位圖、畫刷、字體、筆、區(qū)域等。返回值:如果選擇對象不是區(qū)域并且函數執(zhí)行成功,那么返回值是對象的句柄。,BitBlt()函數,函數功能:該函數對指定的源設備環(huán)境區(qū)域中的像素進行位塊轉換,并傳送到目標設備環(huán)境。函數原型:BOOLBitBlt(HDChdcDest,intnXDest,intnYDest,intnWidth,intnHeight,HDChdcSrc,intnXSrc,intnYSrc,DWORDdwRop);參數:hdcDest:指向目標設備環(huán)境的句柄。nXDest:指定目標矩形區(qū)域左上角的X軸邏輯坐標。nYDest:指定目標矩形區(qū)域左上角的Y軸邏輯坐標。nWidth:指定源和目標矩形區(qū)域的邏輯寬度。nHeight:指定源和目標矩形區(qū)域的邏輯高度。hdcSrc:指向源設備環(huán)境的句柄。nXSrc:指定源矩形區(qū)域左上角的X軸邏輯坐標。nYSrc:指定源矩形區(qū)域左上角的Y軸邏輯坐標。dwRop:指定光柵操作代碼。這些代碼將定義源矩形區(qū)域的顏色數據,如何與目標矩形區(qū)域的顏色數據運算以完成最后的顏色。,常見的光柵操作代碼(dwRop),SRCCOPY:將源矩形區(qū)域直接拷貝到目標矩形區(qū)域。SRCAND:通過使用AND(與)操作符來將源和目標矩形區(qū)域內的顏色合并。SRCPAINT:通過使用布爾型的OR(或)操作符將源和目標矩形區(qū)域的顏色合并。WHITENESS:使用與物理調色板中索引1有關的顏色填充目標矩形區(qū)域。(對于缺省物理調色板來說,這個顏色就是白色)。BLACKNESS:表示使用與物理調色板的索引0相關的色彩來填充目標矩形區(qū)域,(對缺省的物理調色板而言,該顏色為黑色)。DSTINVERT:表示使目標矩形區(qū)域顏色取反。MERGECOPY:表示使用布爾型的AND(與)操作符將源矩形區(qū)域的顏色與特定模式組合一起。MERGEPAINT:通過使用布爾型的OR(或)操作符將反向的源矩形區(qū)域的顏色與目標矩形區(qū)域的顏色合并。NOTSRCCOPY:將源矩形區(qū)域顏色取反,于拷貝到目標矩形區(qū)域。NOTSRCERASE:使用布爾類型的OR(或)操作符組合源和目標矩形區(qū)域的顏色值,然后將合成的顏色取反。,計算機中的GRB顏色,在計算機中,使用的是數字圖像處理,每一種顏色都是由RGB表示的,RGB是指紅(RED)、綠(GREEN)、藍(BLUE)三原色。RGB顏色值是紅綠藍3種顏色的強度,每個原色的GRB顏色值的取值范圍為0(#00)255(#FF)。RGB16進制顏色值即是紅綠藍三原色各自16進制顏色值的組合。如(255,255,255)的16進制顏色值為#FFFFFF。舉例:白色是三原色值均為最大時混合成的的顏色,所以顏色表示為(255,255,255),16進制就用#FFFFFF表示。黑色是三原色值均為最小時混合成的的顏色,所以顏色表示為(0,0,0),16進制就用#000000表示。,在數字圖像處理中可以實現OR、AND等邏輯運算。運算規(guī)律如下:任何顏色同白色(#FFFFFF)進行OR運算結果都為白色,進行AND運算結果都是該顏色本身。任何顏色同黑色(#000000)進行OR運算結果都為該顏色本身,進行AND運算結果都是黑色。例如,可以進行對圖1所示的位圖進行去“背景色”的處理:首先將“圖2”位圖同目標地顏色進行“或”(OR)運算,得到的結果是:“圖2”白色處為白色,其他處為目標地顏色。再將“圖1”位圖同目標地顏色進行“與”(AND)運算,得到的結果是:“圖1”位圖水果處為原顏色,而其他處為目標地顏色,從而達到了精確“去背”的效果。,圖1,圖2,假設,圖1所示的尺寸為160px80px,hdc為內存句柄,picDC為該位圖的內存位圖句柄。則:以下兩條語句會達到的效果:在屏幕(x_pos,y_pos)上顯示“蛇頭朝上”位圖”:BitBlt(hdc,x_pos,y_pos,20,20,picDC,80,20,SRCPAINT);/或運算BitBlt(hdc,x_pos,y_pos,20,20,picDC,0,20,SRCAND);/與運算以下兩條語句會會達到的效果:在屏幕(x_pos,y_pos)上顯示“蛇頭朝下”位圖:BitBlt(hdc,x_pos,y_pos,20,20,picDC,140,20,SRCPAINT);BitBlt(hdc,x_pos,y_pos,20,20,picDC,60,20,SRCAND);,圖1,實現位圖繪圖的核心代碼,HDCwindowDC=NULL;/windows屏幕設備HDCbufferDC=NULL;/緩沖設備環(huán)境HDCpicDC=NULL;/位圖內存設備HBITMAPpicBMP=NULL;/位圖句柄HBITMAPbufferBMP=NULL;/緩沖位圖句柄windowDC=GetDC(NULL);bufferDC=CreateCompatibleDC(windowDC);picDC=CreateCompatibleDC(windowDC);/g_iClientWidth,g_iClientHeight分別是窗口的寬和高。bufferBMP=CreateCompatibleBitmap(windowDC,g_iClientWidth,g_iClientHeight);picBMP=(HBITMAP)LoadImage(NULL,snake.bmp,IMAGE_BITMAP,160,80,LR_LOADFROMFILE);SelectObject(bufferDC,bufferBMP);/將窗口的初始畫面位圖選入緩沖DCSelectObject(picDC,picBMP);/將角色位圖選入選入角色位圖DCBitBlt(bufferDC,x_pos,y_pos,20,20,picDC,80,20,SRCPAINT);/或運算BitBlt(bufferDC,x_pos,y_pos,20,20,picDC,0,20,SRCAND);/與運算/將整個畫面從緩沖DC拷貝出屏幕BitBlt(windowDC,0,0,g_iClientWidth,g_iClientHeight,bufferDC,0,0,SRCCOPY);,4.游戲實例剖析,分析:貪吃蛇游戲是一個深受人們喜愛的游戲,一條蛇在密閉的圍墻內沿當前方向移動,在圍墻內不斷隨機出現水果和毒果。玩家通過按鍵盤上的四個光標鍵控制蛇頭向上下左右四個方向移動,如果蛇頭吃到水果,蛇的身體長一節(jié),分數加100分。如果蛇頭撞到墻壁或蛇頭觸碰到其身體或吃到毒果,游戲結束。,程序的要點:,用一個小矩形塊表示蛇的一節(jié)身體,身體每長一節(jié),增加一個矩形塊。移動時必須從蛇頭開始,所以蛇不能向相反方向移動。如不按任何鍵,蛇自行在當前方向上前移。當游戲者按了有效的方向鍵后,蛇頭朝著指定的方向移動,一步移動一節(jié)身體,所以當按了有效的方向鍵后,先確定蛇頭的位置,然后蛇身體隨著蛇頭移動,圖形的實現是從蛇頭的新位置開始畫出蛇。根據以上分析,設計了兩個類:CTable類、CSnack類。,主要基本數據結構及常量的定義(1),/節(jié)點圖像顯示運動狀態(tài)(方向)enumBitmapStateM_NONE,M_UP_UP,M_DOWN_DOWN,M_LEFT_LEFT,M_RIGHT_RIGHT,M_UP_LEFT,M_UP_RIGHT,M_LEFT_UP,M_LEFT_DOWN,M_RIGHT_UP,M_RIGHT_DOWN,M_DOWN_RIGHT,M_DOWN_LEFT;/節(jié)點運動狀態(tài)(方向)enumMoveStateS_NONE,S_UP,S_DOWN,S_LEFT,S_RIGHT;/坐標位置結構structSPointintx;inty;#defineTB_STATE_OK0/正常#defineTB_STATE_FOOD1/食物#defineTB_STATE_BLOCK2/障礙毒果#defineTB_STATE_SBLOCK3/障礙墻,主要基本數據結構及常量的定義(2),/游戲狀態(tài)定義#defineGAME_STATE_WAIT0/游戲等待狀態(tài)#defineGAME_STATE_RUN1/游戲運行狀態(tài)#defineGAME_STATE_END2/游戲結束狀態(tài)/界面相關物件尺寸定義#defineWALL_WIDTH80/外墻從左部到游戲區(qū)的寬度#defineWALL_HEIGHT80/外墻從頂部到游戲區(qū)的高度#defineBMP_SCORE_BOARD_WIDTH256/分數位圖板的寬度#defineBMP_SCORE_BOARD_HEIGHT55/分數位圖板的高度#defineBMP_WALL_WIDTH16/墻位圖的寬度#defineBMP_WALL_HEIGHT16/墻位圖的高度,classCSnakestructSnake_Struct/定義蛇體狀態(tài)MoveStatehead;/頭部MoveState*body;/身體MoveStatetail;/尾部;private:intm_length;/蛇的長度Snake_Structm_newSnake;/蛇的新態(tài)的所有節(jié)點運動狀態(tài)Snake_Structm_oldSnake;/蛇的原態(tài)的所有節(jié)點運動狀態(tài)BitmapState*m_pStateArray;/蛇的所有節(jié)點顯示位圖的狀態(tài)SPoint*m_pPos;/蛇體坐標private:BitmapStateGetRightState(MoveStateoldDirect,MoveStatenewDirect);/根據新舊兩個身體的運動趨勢情況,返回當前應當顯示的身體狀態(tài)public:voidMove(void);voidChangeDirect(MoveStated);/改變方向,條件:非對立方向voidAddBody(intn=1);/蛇的身體增長voidSetHeadPos(intx,inty);/設置蛇頭的坐標BitmapState*GetStateArray(void);/取蛇的狀態(tài)標識數組SPoint*GetPos(void);/取蛇的位置數組boolIsHeadTouchBody(intx,inty);/檢測蛇頭是否觸碰到其身體intGetLength(void);/取蛇身的長度voidInitial(void);/初始化用作游戲結束后重新開始public:CSnake(intx_pos=0,inty_pos=0,intlen=1);CSnake();,classCTableprivate:intm_width;/桌子的寬度intm_height;/桌子的高度intm_foodNumber;/水果的數目intm_blockNumber;/障礙物(毒果)的數目CSnakem_snake;/桌子上的蛇int*m_board;/桌子面板,二維數組public:CTable();CTable();voidInitialTable(intw,inth);/初始化桌子面板boolAddBlock(intx,inty);/在某個位置放置毒果boolAddFood(intx,inty);/在某個位置放置水果boolClearFood(intx,inty);/清除某個位置的果實CSnake*GetSnake(void);/獲取蛇對象int*GetBoard(void);/取桌子對象intGetData(intx,inty);/取桌子某個位置數據voidSnakeMove(void);/蛇的移動boolChangeSnakeDirect(MoveStated);/改變蛇的方向;,主程序(main.cpp)中的全局變量,CTabletable;/創(chuàng)建一個桌子inttableBlockWidth=0;/桌子的格子的寬度inttableBlockHeight=0;/桌子的格子的高度intiScores=0;/游戲的得分UINTuGameState=GAME_STATE_WAIT;/當前游戲狀態(tài)HDCwindowDC=NULL;/windows屏幕設備HDCbufferDC=NULL;/緩沖設備環(huán)境HDCpicDC=NULL;/snake圖像內存設備HDCendDC=NULL;/游戲終結圖像內存設備HDCscoreDC=NULL;/分數板內存設備HWNDhAppWnd=NULL;/本application窗口句柄HBITMAPpicBMP=NULL;/snake圖像位圖句柄HBITMAPbufferBMP=NULL;/緩沖位圖句柄HBITMAPendBMP=NULL;/游戲終結圖像內存句柄HBITMAPhbmpWall=NULL;/墻位圖句柄HBITMAPhbmpScore=NULL;/分數板位圖句柄HBRUSHhbrushWall=NULL;/墻畫刷UINTuSnakeMoveTimer;/蛇移動的定時器標識UINTuFoodAddTimer;/水果產生的定時器標識/框架的位置數據定義RECTg_ClientRect;RECTg_GameValueRect;intg_iClientWidth;intg_iClientHeight;,intWINAPIWinMain(HINSTANCEhCurrentInst,HINSTANCEhPrevInstance,PSTRlpszCmdLine,intnCmdShow)WNDCLASSwndClass;HWNDhWnd;MSGmsg;UINTwidth,height;/定義窗口wndClass.style=CS_HREDRAW|CS_VREDRAW;wndClass.lpszClassName=Snake_CLASS;/注冊窗口RegisterClass(,WinMain()方法-(1),WinMain()方法-(2),/獲取窗體大小GetClientRect(hAppWnd,WinMain()方法-(3),/聲明位圖與設備環(huán)境的關聯(lián)SelectObject(bufferDC,bufferBMP);SelectObject(picDC,picBMP);SelectObject(endDC,endBMP);SelectObject(scoreDC,hbmpScore);/建立畫刷與其名相對應的圖像的關聯(lián),/以備用刷子將墻刷出來,用PatBlt()實現hbrushWall=CreatePatternBrush(hbmpWall);StartGame();while(GetMessage(,WndProc()方法-(1),LRESULTCALLBACKWndProc(HWNDhWnd,UINTmessage,WPARAMwParam,LPARAMlParam)switch(message)caseWM_TIMER:OnTimer(UINT)wParam);break;caseWM_KEYDOWN:switch(wParam)caseVK_ESCAPE:exit(0);break;caseVK_UP:table.ChangeSnakeDirect(S_UP);break;caseVK_DOWN:table.ChangeSnakeDirect(S_DOWN);break;caseVK_LEFT:table.ChangeSnakeDirect(S_LEFT);break;caseVK_RIGHT:table.ChangeSnakeDirect(S_RIGHT);break;caseVK_SPACE:if(uGameState=GAME_STATE_END)StartGame();break;return0;,WndProc()方法-(2),caseWM_SETCURSOR:SetCursor(NULL);return0;caseWM_DESTROY:ReleaseDC(hWnd,picDC);ReleaseDC(hWnd,bufferDC);ReleaseDC(hWnd,windowDC);PostQuitMessage(0);return0;returnDefWindowProc(hWnd,message,wParam,lParam);,voidStartGame()iScores=0;/桌面的初始化table.InitialTable(tableBlockWidth,tableBlockHeight);table.GetSnake()-ChangeDirect(S_RIGHT);table.GetSnake()-SetHeadPos(tableBlockWidth/2,tableBlockHeight/2);/預先隨機產生幾個食物srand(unsigned)time(NULL);for(intiFoodNum=0;iFoodNumIsHeadTouchBody(table.GetSnake()-GetPos()0.x,table.GetSnake()-GetPos()0.y)EndGame();/根據蛇頭所在的區(qū)域作出相應的處理switch(table.GetData(table.GetSnake()-GetPos()0.x,table.GetSnake()-GetPos()0.y)caseTB_STATE_FOOD:table.ClearFood(table.GetSnake()-GetPos()0.x,table.GetSnake()-GetPos()0.y);table.AddBlock(rand()%tableBlockWidth,(rand()%tableBlockHeight);table.GetSnake()-AddBody();+iScores;break;caseTB_STATE_BLOCK:caseTB_STATE_SBLOCK:EndGame();/檢測是否碰到障礙物,結束游戲break;DrawGame();/顯示elseif(uTIMER_ID=uFoodAddTimer)/定時加食物table.AddFood(rand()%tableBlockWidth,(rand()%tableBlockHeight);,voidDrawGame(void)ShellDraw(bufferDC);/繪制外殼區(qū)域到緩沖GameAreaDraw(bufferDC);/繪制游戲區(qū)域到緩沖/將整個畫面從緩沖DCbufferDC拷貝到屏幕BitBlt(windowDC,0,0,g_iClientWidth,g_iClientHeight,bufferDC,0,0,SRCCOPY);voidShellDraw(HDChdc)/分數提示顯示文字charszText30=Score:;charszNum20;intiNowScore=iScores*100;itoa(iNowScore,szNum,10);strcat(szText,szNum);RECTrt,rect;GetClientRect(hAppWnd,GameAreaDraw()方法-(1),voidGameAreaDraw(HDChdc)inti,j;intx,y,x_pos,y_pos;BitmapStatestate;/繪制水果與毒果for(i=0;iGetPos()0.y;x_pos=x*20+WALL_WIDTH;y_pos=y*20+WALL_HEIGHT;state=table.GetSnake()-GetStateArray()0;switch(state)caseM_UP_UP:BitBlt(hdc,x_pos,y_pos,20,20,picDC,80,20,SRCPAINT);BitBlt(hdc,x_pos,y_pos,20,20,picDC,0,20,SRCAND);break;caseM_DOWN_DOWN:BitBlt(hdc,x_pos,y_pos,20,20,picDC,140,20,SRCPAINT);BitBlt(hdc,x_pos,y_pos,20,20,picDC,60,20,SRCAND);break;caseM_LEFT_LEFT:BitBlt(hdc,x_pos,y_pos,20,20,picDC,100,20,SRCPAINT);BitBlt(hdc,x_pos,y_pos,20,20,picDC,20,20,SRCAND);break;caseM_RIGHT_RIGHT:BitBlt(hdc,x_pos,y_pos,20,20,picDC,120,20,SRCPAINT);BitBlt(hdc,x_pos,y_pos,20,20,picDC,40,20,SRCAND);break;,GameAreaDraw()方法-(3),/根據各個蛇身

溫馨提示

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

評論

0/150

提交評論