实现拖拽,绘制,键盘移动画布三者结合

 实现鼠标在移动的画布上绘制。并且实现了低的占用。分四种情况分别计算坐标,分别进行渲染

#include 
#include 
// 缓冲区纹理映射函数:bkmesh 映射目标,map 映射总网格,pentable:纹理集,bkmeshmapi,bkmeshmapj:映射起始点,tilenum:横,纵映射的数量,pixnum:一个映射块的边长,单位:像素。
void freshmesh(IMAGE* bkmesh, int** map, IMAGE* pentable, int bkmeshmapi, int bkmeshmapj, int tilenum, int pixnum)
{
	int pennumber = 0;										// 暂存每一次循环的映射代号
	IMAGE pen = NULL;											// 所找到的纹理
	int left = 0;												// 这是每次循环所找到的纹理对应映射地址
	int top = 0;
	SetWorkingImage(bkmesh);								// 设置绘图目标为游戏背景采样区,刷新采样区,刷新寄存区
	for (int i = bkmeshmapi; i < bkmeshmapi + tilenum; i++)
	{
		left = 0;
		for (int j = bkmeshmapj; j < bkmeshmapj + tilenum; j++)
		{
			pennumber = map[i][j];							// 读取游戏大地图数组序号
			pen = pentable[pennumber];						// 根据序号查找对应贴图
			putimage(left, top, &pen);						// 把贴图画到采样区
			left += pixnum;									// 往右移动,准备下一次绘制位置
		}
		top += pixnum;										// 往下移动,准备下一次绘制位置
	}
	SetWorkingImage();
}
// 在纹理映射函数中产生的图片中截图,但此为演示参数作用,此处并未优化。
void freshbk(IMAGE* bk, IMAGE* bkmesh, int gamex, int gamey, int bkmeshmapi, int bkmeshmapj, int tilenum, int pixnum)
{
	SetWorkingImage(bkmesh);
	getimage(bk, gamex - bkmeshmapj * pixnum, gamey - bkmeshmapi * pixnum, tilenum * pixnum, tilenum * pixnum);
	SetWorkingImage();
}
// 在屏幕显示截图
void showbk(IMAGE* bk, int bkdeskx, int bkdesky)
{
	SetWorkingImage();
	putimage(bkdeskx, bkdesky, bk);
}
// 在屏幕上显示缓冲区
void showbkmesh(IMAGE* bkmesh, int bkmeshdeskx, int bkmeshdesky)
{
	SetWorkingImage();
	putimage(bkmeshdeskx, bkmeshdesky, bkmesh);
}
int** initmap(int wide,int high)
{
	int**map = new int* [high];							// 二维数组动态初始化,先给二级指针挂上一个长度为 10 的指针数组
	for (int i = 0; i < high ; i++)
	{
		map[i] = new int[wide];						// 然后数组里的每个指针都挂上一个长度为 10 的 int 类型数组
	}
	for (int i = 0; i  bkdeskleft && m.y > bkdesktop && m.x < bkdeskleft + 300 && m.y < bkdesktop + 300)		// 如果之前不是长按状态	且按下左键时,鼠标在游戏背景区域内
					{
						drawflag = 1;																				// 才记录为正在绘制的状态
					}
					else if (drawflag==0&&draftflag==0&&m.x > 0 && m.y > 0 && m.x < 30 && m.y < 300)
					{
						pentake = m.y / 30; 																		// 选择贴图对应的代号
					}
					break;
				case WM_LBUTTONUP:
					drawflag = 0;
					break;
				case WM_RBUTTONDOWN:																				// 鼠标右键拖动
					if (draftflag==0&&m.x > bkdeskleft && m.y > bkdesktop && m.x < bkdeskleft + 270 && m.y < bkdesktop + 270)
					{
						draftflag = 1;
						draftoldmx = m.x;
						draftoldmy = m.y;
						draftoldgamex = bkgameleft;
						draftoldgamey = bkgametop;
					}
					break;
				case WM_RBUTTONUP:
					draftflag = 0;
					bkgameleft = draftoldgamex - (m.x - draftoldmx);												// bkgameleft - draftoldgamex =- (m.x - draftoldmx)
					bkgametop = draftoldgamey - (m.y - draftoldmy);													// bkgametop - draftoldgamey =- (m.y - draftoldmy)
					break;
				case WM_KEYDOWN:
					switch (m.vkcode)					// 键盘移动控制
					{
						case 0x41:						// A
							flag_x-=speed;
							moveflag=1;
							break;
						case 0x57:						// W
							flag_y-=speed;
							break;
						case 0x44:						// D
							flag_x+=speed;
							break;
						case 0x53:						// S
							flag_y+=speed;
							break;
					}
					break;
				case WM_KEYUP:
					switch(m.vkcode)
					{
						case 0x41:						// A
							flag_x=0;
							break;
						case 0x57:						// W
							flag_y=0;
							break;
						case 0x44:						// D
							flag_x=0;
							break;
						case 0x53:						// S
							flag_y=0;
							break;
					}
					break;
				default:
					mousex=m.x;
					mousey=m.y;
					break;
			}
		}
//		开始根据指令运行坐标变化
		if (draftflag == 1)
		{
			bkgameleft = draftoldgamex - (mousex - draftoldmx);											// bkgameleft-draftoldgamex=-(m.x-draftoldmx)
			bkgametop = draftoldgamey - (mousey - draftoldmy);											// bkgametop-draftoldgamey=-(m.y - draftoldmy)
		}
		else if (drawflag == 1&&flag_x==0&&flag_y==0 &&drawoldmx!=mousex&&drawoldmy!=mousey&& mousex > bkdeskleft && mousey > bkdesktop && mousex < bkdeskleft + 300 && mousey < bkdesktop + 300)
		{
			// 注意不要越界,否则 gamex 为负数,导致数组越界闪退。
			// 通过实现坐标变换与赋值达到修改游戏大地图(数组)
			moveflag=0;
			drawoldmx = mousex;
			drawoldmy = mousey;
			drawx = bkgameleft + (mousex - bkdeskleft);										// drawx-bkgameleft=m.x-bkdeskleft	横坐标方向移动距离相同
			drawy = bkgametop + (mousey - bkdesktop);										// drawy-bkgametop=m.y-bkdesktop	纵坐标方向移动距离相同
			map[drawy / pixnum][drawx / pixnum] = pentake;									// 注意 map[y][x],而不是 map[x][y],因为判断第几行,是通过 y 来控制上下移动的,判断第几列,是通过 x 左右移动的。
		}	//	对绘制进行分类计算数据,剥离特殊情况的重复绘制,仅仅是 flag_x,或者flag_y不为零时取消重复绘制判断。
		else if(drawflag == 1 && mousex > bkdeskleft && mousey > bkdesktop && mousex < bkdeskleft + 300 && mousey < bkdesktop + 300)
		{
			moveflag=1;
			while(flag_x<-10)										// 限制在合适速度范围
				flag_x+=10;
			while(flag_x>10)
				flag_x-=10;
			while(flag_y<-10)
				flag_y+=10;
			while(flag_y>10)
				flag_y-=10;
			bkgameleft+=flag_x;
			bkgametop+=flag_y;

			drawx = bkgameleft + (mousex - bkdeskleft);										// drawx-bkgameleft=m.x-bkdeskleft	横坐标方向移动距离相同
			drawy = bkgametop + (mousey - bkdesktop);										// drawy-bkgametop=m.y-bkdesktop	纵坐标方向移动距离相同
			map[drawy / pixnum][drawx / pixnum] = pentake;									// 注意 map[y][x],而不是 map[x][y],因为判断第几行,是通过 y 来控制上下移动的,判断第几列,是通过 x 左右移动的。
		}
		else if(drawflag==0&&flag_x!=0||flag_y!=0)
		{
			moveflag=1;
			while(flag_x<-10)										// 限制在合适速度范围
				flag_x+=10;
			while(flag_x>10)
				flag_x-=10;
			while(flag_y<-10)
				flag_y+=10;
			while(flag_y>10)
				flag_y-=10;
			bkgameleft+=flag_x;
			bkgametop+=flag_y;
		}
		else
		{
			// 既不绘制也不移动也不拖拽
		}
		//		根据计算出的坐标数据进行绘制
		if(drawflag==1&&moveflag==0)																	// 简单的性能优化
		{
			freshmesh(bkmesh, map, pentable, bkmeshmapi, bkmeshmapj, 27, 30);			// 刷新,重新映射,其实就是开头初始化的代码,这里是给了一个封装示例,但未进行性能优化
			freshbk(bk, bkmesh, bkgameleft, bkgametop, bkmeshmapi, bkmeshmapj, 9, 30);
			showbk(bk, bkdeskleft, bkdesktop);
			showbkmesh(bkmesh, bkmeshdeskleft, bkmeshdesktop);
		}
		else if(drawflag==1&&moveflag==1)
		{
			if(bkgameleft<0)															// 网格越界检测并调整
				bkgameleft=0;
			if(bkgametop<0)
				bkgametop=0;
			if(bkgameleft>30*300)
				bkgameleft=30*300;
			if(bkgametop>30*300)
				bkgametop=30*300;
			while (bkgameleft < bkmeshgameleft)											// 更新游戏采样区坐标,一些简单换算
				bkmeshgameleft -=270;
			while (bkgametop bkmeshgameleft+270+270)
				bkmeshgameleft += 270;
			while(bkgametop>bkmeshgametop+270+270)
				bkmeshgametop += 270;
			bkmeshmapi = bkmeshgametop / pixnum;
			bkmeshmapj = bkmeshgameleft / pixnum;
			freshmesh(bkmesh, map, pentable, bkmeshmapi, bkmeshmapj, 27, 30);
			freshbk(bk, bkmesh, bkgameleft, bkgametop, bkmeshmapi, bkmeshmapj, 9, 30);
			showbkmesh(bkmesh, bkmeshdeskleft, bkmeshdesktop);
			showbk(bk, bkdeskleft, bkdesktop);
		}
		else if(moveflag==1)																// 分类渲染,drawflag==0 时 
		{
			if(bkgameleft<0)															// 网格越界检测并调整
				bkgameleft=0;
			if(bkgametop<0)
				bkgametop=0;
			if(bkgameleft>30*300)
				bkgameleft=30*300;
			if(bkgametop>30*300)
				bkgametop=30*300;
			while (bkgameleft < bkmeshgameleft)											// 更新游戏采样区坐标,一些简单换算
				bkmeshgameleft -=270;
			while (bkgametop bkmeshgameleft+270+270)
				bkmeshgameleft += 270;
			while(bkgametop>bkmeshgametop+270+270)
				bkmeshgametop += 270;
			bkmeshmapi = bkmeshgametop / pixnum;
			bkmeshmapj = bkmeshgameleft / pixnum;
			if(oldbkmeshgamex!=bkmeshgameleft||oldbkmeshgamey!=bkmeshgametop)			// 判断是否更新采样区
			{
				freshmesh(bkmesh, map, pentable, bkmeshmapi, bkmeshmapj, 27, 30);
				oldbkmeshgamex=bkmeshgameleft;
				oldbkmeshgamey=bkmeshgametop;
				showbkmesh(bkmesh, bkmeshdeskleft, bkmeshdesktop);
			}
			freshbk(bk, bkmesh, bkgameleft, bkgametop, bkmeshmapi, bkmeshmapj, 9, 30);
			showbk(bk, bkdeskleft, bkdesktop);
		}
		else if(draftflag)																// 分类渲染-只拖拽
		{
			if(bkgameleft<0)															// 网格越界检测并调整
				bkgameleft=0;
			if(bkgametop<0)
				bkgametop=0;
			if(bkgameleft>30*300)
				bkgameleft=30*300;
			if(bkgametop>30*300)
				bkgametop=30*300;
			while (bkgameleft < bkmeshgameleft)											// 更新游戏采样区坐标,一些简单换算
				bkmeshgameleft -=270;
			while (bkgametop bkmeshgameleft+270+270)
				bkmeshgameleft += 270;
			while(bkgametop>bkmeshgametop+270+270)
				bkmeshgametop += 270;
			bkmeshmapi = bkmeshgametop / pixnum;
			bkmeshmapj = bkmeshgameleft / pixnum;
			if(oldbkmeshgamex!=bkmeshgameleft||oldbkmeshgamey!=bkmeshgametop)			// 判断是否更新采样区
			{
				freshmesh(bkmesh, map, pentable, bkmeshmapi, bkmeshmapj, 27, 30);
				oldbkmeshgamex=bkmeshgameleft;
				oldbkmeshgamey=bkmeshgametop;
				showbkmesh(bkmesh, bkmeshdeskleft, bkmeshdesktop);
			}
			freshbk(bk, bkmesh, bkgameleft, bkgametop, bkmeshmapi, bkmeshmapj, 9, 30);
			showbk(bk, bkdeskleft, bkdesktop);
		}
		Sleep(20);																		// 休眠 20 毫秒,减少 CPU 占用
	}
	return 0;
}
// 边界 2.55GHz 3%占用,内部 2.45Ghz 

你可能感兴趣的:(计算机外设,算法,数据结构)