利用VS创建一个游戏(3)游戏地图绘制(代码+注释)

首先注意的是我们要将地图素材放置项目文件夹中。

#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);

效果分别如下:




猜你喜欢

转载自blog.csdn.net/hao5119266/article/details/80152923