利用VS建立一個遊戲(3)遊戲地圖繪製(程式碼+註釋)
阿新 • • 發佈:2019-01-31
首先注意的是我們要將地圖素材放置專案資料夾中。
#include "stdafx.h" #include "MyGameFrame.h" //源cpp檔案引申出的標頭檔案 也可以用resource.h代替 #include <stdio.h> //標準輸入輸出標頭檔案 // 全域性變數: HINSTANCE hInst; // 當前例項 HWND hWnd; HDC mdc; //記憶體DC HDC hdc; HBITMAP fullmap; //地圖 const int cols = 8; const int rows = 8; // 此程式碼模組中包含的函式的前向宣告: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitWindow(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 初始化全域性字串 MyRegisterClass(hInstance); // 執行應用程式初始化: if (!InitWindow(hInstance, nCmdShow))//初始化視窗 { return FALSE;//如果不成功則返回FALSE,並退出程式 } /* MSG型別見 https://blog.csdn.net/wanghaofeng/article/details/6632165 */ MSG msg; //建立訊息類物件 // TODO: 在此放置執行程式碼。 HDC hdc = GetDC(hWnd);//建立記憶體DC mdc = CreateCompatibleDC(hdc);//建立視窗DC,CreateCompatibleDC( )函式建立建立記憶體裝置描述表,把儲存在記憶體DC上的點陣圖貼到視窗DC中 HDC bufdc = CreateCompatibleDC(hdc); //檔名 char filename[20] = ""; //行列及座標 int rowNum, colNum; int i, x, y; //---------------------------------------------平面地圖貼圖方式-------------------------------------------------------------- //地圖陣列 int mapIndex[64] = { 2,2,2,2,0,1,0,1, //第1行 0,2,2,0,0,0,1,1, //第2行 0,0,0,0,0,0,0,1, //第3行 2,0,0,0,0,0,2,2, //第4行 2,0,0,0,0,2,2,2, //第5行 2,0,0,0,2,2,0,0, //第6行 0,0,2,2,2,0,0,1, //第7行 0,0,2,0,0,0,1,1 //第8行 }; fullmap = CreateCompatibleBitmap(hdc, cols * 50, rows * 50);//cols列數 rows行數 SelectObject(mdc, fullmap); //儲存三種不同的地圖格式 HBITMAP map[3]; //載入各圖塊點陣圖 for (i = 0; i<3; i++) { sprintf_s(filename, "map%d.bmp", i); map[i] = (HBITMAP)LoadImage(NULL, filename, IMAGE_BITMAP, 50, 50, LR_LOADFROMFILE); } //計算圖塊貼圖位置並進行地圖拼接並繪製的 for (i = 0; i<rows*cols; i++) { SelectObject(bufdc, map[mapIndex[i]]); rowNum = i / cols; //求行編號 colNum = i % cols; //求列編號 x = colNum * 50; //求貼圖X 座標 y = rowNum * 50; //求貼圖Y 座標 BitBlt(mdc, x, y, 50, 50, bufdc, 0, 0, SRCCOPY); //地圖拼接 } //---------------------------------------------------------------------------------------------------------------------------- SelectObject(mdc, fullmap); BitBlt(hdc, 0, 0, cols * 50, rows * 50, mdc, 0, 0, SRCCOPY); //主訊息迴圈: PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);//賦初值 while (msg.message != WM_QUIT) //進入遊戲訊息迴圈: { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); //獲得遊戲玩家輸入的訊息; DispatchMessage(&msg);//分配玩家訊息並響應使用者訊息。 } } return (int)msg.wParam; } // // 函式: MyRegisterClass() // // 註冊Windows類,一款遊戲有且僅有一個主視窗,與遊戲程式唯一對應。建立遊戲視窗前要填寫視窗類結構體WNDCLASSEX // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex = { wcex.cbSize = sizeof(WNDCLASSEX), CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW, WndProc,0,0, hInstance, LoadIcon(hInstance, (LPCTSTR)IDI_MYGAMEFRAME), LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1),NULL, _T("GameFrame"), LoadIcon(NULL,(LPCTSTR)IDI_SMALL) }; return RegisterClassEx(&wcex); } // // 函式: InitInstance(HINSTANCE, int) // // 目的: 儲存例項控制代碼並建立主視窗 // // 註釋: // // 在此函式中,我們在全域性變數中儲存例項控制代碼並 // 建立和顯示主程式視窗。 // BOOL InitWindow(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // 將例項控制代碼儲存在全域性變數中 hWnd = CreateWindow ( _T("GameFrame"), _T("遊戲框架"), WS_OVERLAPPEDWINDOW^WS_THICKFRAME^WS_MAXIMIZEBOX,//普通樣式,不能改變大小,不能最大化 CW_USEDEFAULT, CW_USEDEFAULT, 400, 400, nullptr, nullptr, hInstance, nullptr ); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // 函式: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目的: 處理主視窗的訊息。 // // WM_COMMAND - 處理應用程式選單 // WM_PAINT - 繪製主視窗 // WM_DESTROY - 傳送退出訊息並返回 // // LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { PAINTSTRUCT ps; //用於WM_PAINT switch (msg) //判斷訊息 { case WM_CREATE: //執行初始化程式碼 return(0); break; case WM_PAINT: //確定視窗是否有效 hdc = BeginPaint(hwnd, &ps); //執行繪製程式碼 SelectObject(mdc, fullmap); //影象重繪處要加上這兩句程式碼 BitBlt(hdc, 0, 0, cols * 50, rows * 50, mdc, 0, 0, SRCCOPY); //繪製 //結束程式碼 EndPaint(hwnd, &ps); return(0); break; case WM_DESTROY: //關閉程式,傳送WM_QUIT訊息 PostQuitMessage(0); return(0); break; default: break; } return (DefWindowProc(hwnd, msg, wparam, lparam)); }
測試結果如下:
同樣我們要繪製斜角地圖,我們先將地圖大小做更換
全域性變數裡更改
const int cols = 8;
const int rows = 8;
同樣我們要繪製斜角地圖,先將標線部分更換為
//-----------------------------------------斜角地圖貼圖方式(需把其他貼圖方式註釋掉)------------------------------------------ //地圖陣列 int mapIndex[100] = { 2,2,2,2,2,0,1,0,1,0, //第1行 3,3,2,2,0,0,0,1,1,0, //第2行 3,0,0,0,0,0,0,0,1,2, //第3行 2,2,0,0,0,0,0,2,2,2, //第4行 2,2,0,0,0,0,2,2,2,2, //第5行 2,2,0,0,0,2,2,0,0,2, //第6行 2,0,0,2,2,2,0,0,1,0, //第7行 0,0,2,0,0,0,1,1,1,1, //第8行 0,2,0,3,3,3,3,3,3,1, //第9行 2,0,3,3,3,3,3,3,3,3 //第10行 }; //-------------------景物地圖貼圖方式使用----------------------------------------- //景物陣列sceneIndex[100]: int sceneIndex[100] = { 0,2,2,0,2,0,1,0,1,1, //景物 0,0,0,0,0,0,0,1,1,0, 0,0,0,0,0,0,1,0,1,0, 0,0,1,0,1,0,0,0,2,0, 2,2,0,0,1,0,0,0,0,2, 0,0,0,0,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,1,1,1, 1,0,0,0,0,0,0,0,0,1, 2,0,0,0,0,0,0,0,0,0 }; //----------------------------------------------------------------------------------- //儲存四種不同的地圖格式 HBITMAP map[4]; //xstart與ystart表示第一張圖塊左上角貼圖座標 int xstart, ystart; xstart = 32 * (rows - 1);//每個菱形的大小為64*32所以第0行第0列小圖塊座標應該為此應該是(行數-1)*32 ystart = 160; //從y=160處開始繪製地圖(即視窗高1/3處開始) fullmap = (HBITMAP)LoadImage(NULL, "bgtwo.bmp", IMAGE_BITMAP, 640, 480, LR_LOADFROMFILE); SelectObject(mdc, fullmap); for (i = 0; i<4; i++) { sprintf_s(filename, "maptwo%d.bmp", i); map[i] = (HBITMAP)LoadImage(NULL, filename, IMAGE_BITMAP, 128, 32, LR_LOADFROMFILE); } //載入景物點陣圖 HBITMAP scene[2]; for (i = 0; i<2; i++) { sprintf_s(filename, "scene%d.bmp", i + 1); scene[i] = (HBITMAP)LoadImage(NULL, filename, IMAGE_BITMAP, 100, 60, LR_LOADFROMFILE); } //計算圖塊貼圖位置程式程式碼 for (i = 0; i<rows*cols; i++) { SelectObject(bufdc, map[mapIndex[i]]); rowNum = i / cols; //求行編號 colNum = i % cols; //求列編號 x = xstart + colNum * 32 + rowNum * (-32); //求貼圖X 座標 y = ystart + rowNum * 16 + colNum * 16; //求貼圖Y 座標 BitBlt(mdc, x, y, 64, 32, bufdc, 64, 0, SRCAND); //透明處理 BitBlt(mdc, x, y, 64, 32, bufdc, 0, 0, SRCPAINT); //貼圖座標修正程式碼 //-------------------景物地圖貼圖方式使用----------------------------------------- switch (sceneIndex[i]) { case 1: SelectObject(bufdc, scene[0]); BitBlt(mdc, x + 7, y - 44, 50, 60, bufdc, 50, 0, SRCAND); //景物1 BitBlt(mdc, x + 7, y - 44, 50, 60, bufdc, 0, 0, SRCPAINT); break; case 2: SelectObject(bufdc, scene[1]); BitBlt(mdc, x + 7, y - 30, 50, 60, bufdc, 50, 0, SRCAND); //景物2 BitBlt(mdc, x + 7, y - 30, 50, 60, bufdc, 0, 0, SRCPAINT); break; } //------------------------------------------------------------------------------- } SelectObject(mdc, fullmap); BitBlt(hdc, 0, 0, 640, 480, mdc, 0, 0, SRCCOPY);
然後更換視窗大小 :(InitWindow()函式中)
HWND hWnd = CreateWindow
(
_T("GameFrame"),
_T("遊戲框架"),
WS_OVERLAPPEDWINDOW^WS_THICKFRAME^WS_MAXIMIZEBOX,//普通樣式,不能改變大小,不能最大化
CW_USEDEFAULT, CW_USEDEFAULT,640,480, nullptr, nullptr, hInstance, nullptr
);
更換繪製程式碼:(WndProc()函式中)
SelectObject(mdc, fullmap); BitBlt(hdc, 0, 0, 640, 480, mdc, 0, 0, SRCCOPY);
效果分別如下: