我想做三国志

努力学习做游戏的小白

伴随角色的移动,地图自动扩大的实现 银牌收录

操作方法

方向键控制红点移动,移动过的地方成为地图,回车键退出。

简单说明

GetImageHDC 可以获取设备 HDC(Handle Device Context 设备上下文句柄),StretchBlt 可以把一个 HDC 的内容缩放后输出到另一个 HDC 上,GetImageBuffer 可以获取 IMAGE 类的缓冲区,操作这个缓冲区可以改变 IMAGE 也就是图像的内容。这三个函数十分简便地实现了地图缩放。

程序截图

代码实现

////////////////////////////////////////////
// 程序:伴随角色的移动,地图自动扩大的实现
// 作者:我想做三国志
// 编译环境:Visual Studio 2019,EasyX_20220901
// 编写日期:2023-2-25

#include <graphics.h>

const int WIDTH = 640;		// 屏幕宽度
const int HEIGHT = 480;		// 屏幕高度
const int UP = 0;			// 上方向
const int DOWN = 2;			// 下方向
const int LEFT = 1;			// 左方向
const int RIGHT = 3;		// 右方向
const int NONE = 4;			// 空方向
const int COLNUM = 3;		// 颜色数量
const int NODEWIDTH = 4;	// 节点宽度
const int NODEHEIGHT = 4;	// 节点高度
const int PATHWIDTH = 2;	// 路径宽度
const int PATHLEN = 1;		// 路径长度

COLORREF ColArr[COLNUM] = { BLACK, WHITE, RED };	// 颜色数组

// 画节点
void DrawNode(DWORD* buf, int LeftEst, int RightEst, int UpEst, int DownEst, int x, int y, char element)
{
	setfillcolor(ColArr[element]);
	solidrectangle(x * (NODEWIDTH + PATHLEN), y * (NODEHEIGHT + PATHLEN), x * (NODEWIDTH + PATHLEN) + NODEWIDTH - 1, y * (NODEHEIGHT + PATHLEN) + NODEHEIGHT - 1);
	if (element == COLNUM + 1)
	{
		int radius = min(NODEHEIGHT, NODEWIDTH) / 2;
		setfillcolor(RED);
		solidcircle(x * (NODEWIDTH + PATHLEN) + radius, y * (NODEHEIGHT + PATHLEN) + radius, radius);
	}
}

// 画路径
void DrawPath(DWORD* buf, int LeftEst, int RightEst, int UpEst, int DownEst, int x, int y, char Dir)
{
	int beginPX = x * (PATHLEN + NODEWIDTH), beginPY = y * (NODEHEIGHT + PATHLEN);
	int height = PATHWIDTH, width = PATHWIDTH;
	switch (Dir)
	{
	case UP:	beginPX += (NODEWIDTH - PATHWIDTH) / 2; beginPY -= PATHLEN;	height = PATHLEN;	break;
	case DOWN:	beginPX += (NODEWIDTH - PATHWIDTH) / 2; beginPY += NODEHEIGHT;	height = PATHLEN;	break;
	case LEFT:	beginPY += (NODEHEIGHT - PATHWIDTH) / 2; beginPX -= PATHLEN;	width = PATHLEN;	break;
	case RIGHT:	beginPY += (NODEHEIGHT - PATHWIDTH) / 2; beginPX += NODEWIDTH;	width = PATHLEN;	break;
	}
	setfillcolor(WHITE);
	solidrectangle(beginPX, beginPY, beginPX + width - 1, beginPY + height - 1);
}

// 画地图
void DrawMap(DWORD* buf, int LeftEst, int RightEst, int UpEst, int DownEst, char* AuxiliaryMap, char* PathHoriMap, char* PathVertMap)
{
	// 画节点
	for (int i = 0; i < DownEst - UpEst + 1; i++)
		for (int j = 0; j < RightEst - LeftEst + 1; j++)
			DrawNode(buf, LeftEst, RightEst, UpEst, DownEst, j, i, AuxiliaryMap[i * (RightEst - LeftEst + 1) + j]);

	// 画横向道路
	for (int i = 0; i < DownEst - UpEst + 1; i++)
		for (int j = 0; j < RightEst - LeftEst; j++)
			if (PathHoriMap[i * (RightEst - LeftEst) + j] == 1)
				DrawPath(buf, LeftEst, RightEst, UpEst, DownEst, j, i, RIGHT);

	// 画竖向道路
	for (int i = 0; i < DownEst - UpEst; i++)
		for (int j = 0; j < RightEst - LeftEst + 1; j++)
			if (PathVertMap[i * (RightEst - LeftEst + 1) + j] == 1)
				DrawPath(buf, LeftEst, RightEst, UpEst, DownEst, j, i, DOWN);
}

// 主函数
int main()
{
	initgraph(WIDTH, HEIGHT);
	BeginBatchDraw();

	HDC mainDC = GetImageHDC(NULL);			// 主窗口的 DC
	SetStretchBltMode(mainDC, HALFTONE);	// 设置拉伸贴图模式

	int beginX = 0, beginY = 0;
	int LeftEst = -3, RightEst = 3, UpEst = -3, DownEst = 3;
	int showWidth = WIDTH - 50, showHeight = HEIGHT - 50;
	char* AuxiliaryMap = new char[(RightEst - LeftEst + 1) * (DownEst  - UpEst   + 1)];
	char* PathHoriMap  = new char[(RightEst - LeftEst) 	   * (DownEst  - UpEst   + 1)];
	char* PathVertMap  = new char[(DownEst  - UpEst) 	   * (RightEst - LeftEst + 1)];
	memset(AuxiliaryMap, 0, sizeof(char) * (RightEst - LeftEst + 1) * (DownEst  - UpEst   + 1));
	memset(PathHoriMap,  0, sizeof(char) * (RightEst - LeftEst) 	* (DownEst  - UpEst   + 1));
	memset(PathVertMap,  0, sizeof(char) * (DownEst  - UpEst) 		* (RightEst - LeftEst + 1));
	AuxiliaryMap[(beginY + abs(UpEst)) * (RightEst - LeftEst + 1) + beginX + abs(LeftEst)] = COLNUM - 1;

	// 建立 img 对象
	IMAGE img((NODEWIDTH + PATHLEN) * (RightEst - LeftEst + 1) - PATHLEN, (NODEHEIGHT + PATHLEN) * (DownEst - UpEst + 1) - PATHLEN);
	HDC imgDC = GetImageHDC(&img);
	DWORD* pBuf = GetImageBuffer(&img);
	memset(pBuf, 0, sizeof(DWORD) * img.getwidth() * img.getheight());
	SetWorkingImage(&img);
	DrawMap(pBuf, LeftEst, RightEst, UpEst, DownEst, AuxiliaryMap, PathHoriMap, PathVertMap);

	// 贴图到主窗口
	double times = min(showHeight / (double)img.getheight(), showWidth / (double)img.getwidth());
	int BeginShowPX = (WIDTH - showWidth) / 2 + (showWidth - img.getwidth() * times) / 2;
	int BeginShowPY = (HEIGHT - showHeight) / 2 + (showHeight - img.getheight() * times) / 2;
	SetWorkingImage(NULL);
	StretchBlt(mainDC, BeginShowPX, BeginShowPY, (int)(img.getwidth() * times + 0.5), (int)(img.getheight() * times + 0.5),
			   imgDC,  0, 0, img.getwidth(), img.getheight(), SRCCOPY);
	FlushBatchDraw();

	bool isExit = false;
	ExMessage msg;
	while (!isExit)
	{
		msg = getmessage(EX_KEY);
		if (msg.message == WM_KEYDOWN)
		{
			int newX = beginX, newY = beginY;
			char Dir = NONE;
			switch (msg.vkcode)
			{
			case VK_UP:		newY--; Dir = UP;	 break;
			case VK_DOWN:	newY++; Dir = DOWN;	 break;
			case VK_LEFT:	newX--; Dir = LEFT;	 break;
			case VK_RIGHT:	newX++; Dir = RIGHT; break;
			case VK_RETURN:	isExit = true;		 break;
			}
			if (isExit) break;
			int oriX = abs(LeftEst), oriY = abs(UpEst), oriH = DownEst - UpEst + 1, oriW = RightEst - LeftEst + 1;
			bool isRefresh = false;
			if (newX < LeftEst)
			{
				LeftEst--;
				isRefresh = true;
			}
			else if (newX > RightEst)
			{
				RightEst++;
				isRefresh = true;
			}
			if (newY < UpEst)
			{
				UpEst--;
				isRefresh = true;
			}
			else if (newY > DownEst)
			{
				DownEst++;
				isRefresh = true;
			}
			SetWorkingImage(&img);
			if (isRefresh)
			{
				char* tempAuxiliaryMap = new char[(RightEst - LeftEst + 1) * (DownEst  - UpEst   + 1)];
				char* tempPathHoriMap  = new char[(RightEst - LeftEst)	   * (DownEst  - UpEst   + 1)];
				char* tempPathVertMap  = new char[(DownEst  - UpEst)	   * (RightEst - LeftEst + 1)];
				memset(tempAuxiliaryMap, 0, sizeof(char) * ((RightEst - LeftEst + 1) * (DownEst - UpEst + 1)));
				memset(tempPathHoriMap,  0, sizeof(char) * (RightEst  - LeftEst)	 * (DownEst - UpEst + 1));
				memset(tempPathVertMap,  0, sizeof(char) * (DownEst   - UpEst)		 * (RightEst - LeftEst + 1));
				int beginXX = abs(LeftEst) - oriX, beginYY = abs(UpEst) - oriY;
				for (int i = 0; i < oriH; i++)
					for (int j = 0; j < oriW; j++)
						tempAuxiliaryMap[(beginYY + i) * (RightEst - LeftEst + 1) + beginXX + j] = AuxiliaryMap[i * oriW + j];

				for (int i = 0; i < oriH; i++)
					for (int j = 0; j < oriW - 1; j++)
						tempPathHoriMap[(beginYY + i) * (RightEst - LeftEst) + beginXX + j] = PathHoriMap[i * (oriW - 1) + j];

				for (int i = 0; i < oriH - 1; i++)
					for (int j = 0; j < oriW; j++)
						tempPathVertMap[(beginYY + i) * (RightEst - LeftEst + 1) + beginXX + j] = PathVertMap[i * oriW + j];

				delete[] AuxiliaryMap;
				delete[] PathHoriMap;
				delete[] PathVertMap;
				AuxiliaryMap = tempAuxiliaryMap;
				PathHoriMap = tempPathHoriMap;
				PathVertMap = tempPathVertMap;
				img.Resize((NODEWIDTH + PATHLEN) * (RightEst - LeftEst + 1) - PATHLEN, (NODEHEIGHT + PATHLEN) * (DownEst - UpEst + 1) - PATHLEN);
				imgDC = GetImageHDC(&img);
				pBuf = GetImageBuffer(&img);
				memset(pBuf, 0, sizeof(DWORD) * img.getwidth() * img.getheight());
				DrawMap(pBuf, LeftEst, RightEst, UpEst, DownEst, AuxiliaryMap, PathHoriMap, PathVertMap);

				times = min(showHeight / (double)img.getheight(), showWidth / (double)img.getwidth());
				BeginShowPX = (WIDTH  - showWidth)  / 2 + (showWidth  - img.getwidth()  * times) / 2;
				BeginShowPY = (HEIGHT - showHeight) / 2 + (showHeight - img.getheight() * times) / 2;
			}
			AuxiliaryMap[(beginY + abs(UpEst)) * (RightEst - LeftEst + 1) + beginX + abs(LeftEst)] = 1;
			AuxiliaryMap[(newY   + abs(UpEst)) * (RightEst - LeftEst + 1) + newX   + abs(LeftEst)] = 2;
			DrawNode(pBuf, LeftEst, RightEst, UpEst, DownEst, beginX + abs(LeftEst), beginY + abs(UpEst),
				AuxiliaryMap[(beginY + abs(UpEst)) * (RightEst - LeftEst + 1) + beginX + abs(LeftEst)]);
			DrawNode(pBuf, LeftEst, RightEst, UpEst, DownEst, newX + abs(LeftEst), newY + abs(UpEst),
				AuxiliaryMap[(newY + abs(UpEst)) * (RightEst - LeftEst + 1) + newX + abs(LeftEst)]);
			DrawPath(pBuf, LeftEst, RightEst, UpEst, DownEst, beginX + abs(LeftEst), beginY + abs(UpEst), Dir);
			switch (Dir)
			{
			case UP:	PathVertMap[(newY   + abs(UpEst)) * (RightEst - LeftEst + 1) + newX   + abs(LeftEst)] = 1; break;
			case DOWN:	PathVertMap[(beginY + abs(UpEst)) * (RightEst - LeftEst + 1) + beginX + abs(LeftEst)] = 1; break;
			case LEFT:	PathHoriMap[(newY   + abs(UpEst)) * (RightEst - LeftEst)     + newX   + abs(LeftEst)] = 1; break;
			case RIGHT:	PathHoriMap[(beginY + abs(UpEst)) * (RightEst - LeftEst)     + beginX + abs(LeftEst)] = 1; break;
			}
			beginX = newX;
			beginY = newY;
		}
		SetWorkingImage(NULL);
		cleardevice();
		StretchBlt(mainDC, BeginShowPX, BeginShowPY, img.getwidth() * times, img.getheight() * times,
				   imgDC,  0, 0, img.getwidth(), img.getheight(), SRCCOPY);
		FlushBatchDraw();
	}
	delete[] AuxiliaryMap;
	delete[] PathHoriMap;
	delete[] PathVertMap;
	closegraph();
	return 0;
}

评论 (1) -

添加评论