实现Kruskal算法连通游戏地图地牢

news2024/11/15 15:43:49

前置知识 

c分享|并查集从入门到出门 - 力扣(LeetCode)

 彻底搞懂克鲁斯卡尔(Kruskal)算法(附C++代码实现) - QuanHa - 博客园 (cnblogs.com)

 

白色点矩形是地牢,其中白线是按照krsukal算法连接的画总长最短的线连出来的路径

 

 

 

其中关键算法

#include <stdio.h>

#define MAX_VEX 12
#define MAX_EDGE 144

typedef struct edge {
	int startpoint;							// 起点在数组中的序号
	int endpoint;							// 终点在数组中的序号
	int weight;
} edge;

typedef struct link {
	int startx;									// 起点的坐标
	int starty;
	int endx;									// 终点的坐标
	int endy;
	int used;									// 是否已经使用
	int lenth;									// 距离
	edge edgelink;
} link;

typedef struct target {
	int targeti = 0;							// 左上角网格坐标
	int targetj = 0;
	int targetwidth = 0;						// 长宽
	int targetheight = 0;
	int islive = 0;

//	RenderTexture2D* picture;					// 敌人贴图
//	RenderTexture2D picture;					// 敌人贴图

	int** oldmap;								// 局部复原数据

	int** mapv3;								// 像素也当成网格,每个记录像素是否能穿过

	target* area;								// 敌人内部的点

	int arealenth;								// 用于记录范围,lenth是半径
} target;



int find_root(int roots[], int n) {
	while (roots[n] != -1) {
		n = roots[n];
	}
	return n;
}




int main() {

	
	link linkside[12][12];			// 兼容之前参数


	int vex = 12;					//顶点个数
	int edgeside = 12 * 12;			//边个数

	link graph[MAX_EDGE];
	edge graphv2[MAX_EDGE];

//
//	for (int k = 0; k < edgeside; k++) {
//		for (int n = 0; n <= 11; n++) {
//			for (int m = 0; m <= 11; m++) {
//				if (linkside[n][m].used == 0) {
//					graph[k].startx = linkside[n][m].startx;
//					graph[k].starty = linkside[n][m].starty;
//					graph[k].endx = linkside[n][m].endx;
//					graph[k].endy = linkside[n][m].endy;
//					graph[k].lenth = linkside[n][m].lenth;
//					graph[k].used = 1;
//
//					graphv2[k].startpoint=n;
//					graphv2[k].endpoint=m;
//					graph[k].lenth=linkside[n][m].lenth;
//				}
//			}
//		}
//	}


	for (int n = 0; n < 144; n++) {
		graph[n].used = 0;
	}

	int k = 0;
	for (int n = 0; n <= 11; n++) {
		for (int m = 0; m <= 11; m++) {
			if (linkside[n][m].used == 0) {

				graph[k].startx = linkside[n][m].startx;
				graph[k].starty = linkside[n][m].starty;
				graph[k].endx = linkside[n][m].endx;
				graph[k].endy = linkside[n][m].endy;
				graph[k].lenth = linkside[n][m].lenth;
				graph[k].used = 1;

				graph[k].edgelink.startpoint = n;
				graph[k].edgelink.endpoint = m;
				graph[k].edgelink.weight = linkside[n][m].lenth;
				k++;
			}
		}
	}

//	标记不用数据
	for (int n = 0; n < 144; n++) {
		if (graph[n].used == 0) {
			graph[n].lenth = 999999;
			graph[n].edgelink.weight = 999999;
		}
	}

	// 插入排序
	link max;
	int index;
	for (int n = 0; n < 144; n++) {
		index = n;
		max = graph[n];
		for (int m = n + 1; m < 144; m++) {
			if (graph[m].lenth < max.lenth) {
				max = graph[m];
				index = m;
			}
		}
		graph[index] = graph[n];
		graph[n] = max;
	}


	int roots[MAX_VEX];  	//根数组,存放各顶点的根节点,以区别是否属于同一个集合
	edge MST[MAX_EDGE];		//存放最小生成树(minimum spanning tree)
	int count = 0;


	for (int n = 0; n < MAX_VEX; n++) {
		roots[n] = -1;
	}


//	for (int n = 0; n < MAX_EDGE; n++) {
//
//	}

	for (int n = 0; n < MAX_EDGE; n++) {

		if (graph[n].used == 1) {
			int vex_m = find_root(roots, graph[n].edgelink.startpoint);
			int vex_n = find_root(roots, graph[n].edgelink.endpoint);
			if (vex_m != vex_n) {				//如果两者的根节点不同,说明他们属于不同的集合,可以相连
				MST[count] = graph[n].edgelink;//将此边放入MST数组
				count++;
				roots[vex_m] = vex_n;			//将两个树合并,即将顶点vex_n作为vex_m的根节点

			}
			if (count == vex - 1) {
				break;
			}

		}

	}
	
	for (int i = 0; i < vex - 1; i++)
	{
		printf("(%d,%d)%d\n", MST[i].startpoint, MST[i].endpoint, MST[i].weight);   //打印最小生成树
	}
	
	
	return 0;
}
	int vex = 12;					//顶点个数
		int edgeside = 12 * 12;			//边个数

		link graph[MAX_EDGE];
		edge graphv2[MAX_EDGE];

		/*
		//	for (int k = 0; k < edgeside; k++) {
		//		for (int n = 0; n <= 11; n++) {
		//			for (int m = 0; m <= 11; m++) {
		//				if (linkside[n][m].used == 0) {
		//					graph[k].startx = linkside[n][m].startx;
		//					graph[k].starty = linkside[n][m].starty;
		//					graph[k].endx = linkside[n][m].endx;
		//					graph[k].endy = linkside[n][m].endy;
		//					graph[k].lenth = linkside[n][m].lenth;
		//					graph[k].used = 1;
		//
		//					graphv2[k].startpoint=n;
		//					graphv2[k].endpoint=m;
		//					graph[k].lenth=linkside[n][m].lenth;
		//				}
		//			}
		//		}
		//	}
		*/

		for (int n = 0; n < 144; n++) {
			graph[n].used = 0;
		}
//
		int k = 0;
		for (int n = 0; n <= 11; n++) {
			for (int m = 0; m <= 11; m++) {
				if (linkside[n][m].used == 0) {

					graph[k].startx = linkside[n][m].startx;
					graph[k].starty = linkside[n][m].starty;
					graph[k].endx = linkside[n][m].endx;
					graph[k].endy = linkside[n][m].endy;
					graph[k].lenth = linkside[n][m].lenth;
					graph[k].used = 1;

					graph[k].edgelink.startpoint = n;
					graph[k].edgelink.endpoint = m;
					graph[k].edgelink.weight = linkside[n][m].lenth;
					k++;
				}
			}
		}

//	标记不用数据
		for (int n = 0; n < MAX_EDGE; n++) {
			if (graph[n].used == 0) {
				graph[n].lenth = 999999;
				graph[n].edgelink.weight = 999999;
			}
		}

		// 插入排序
		link max;
		int index;
		for (int n = 0; n < MAX_EDGE; n++) {
			index = n;
			max = graph[n];
			for (int m = n + 1; m < MAX_EDGE; m++) {
				if (graph[m].lenth < max.lenth) {
					max = graph[m];
					index = m;
				}
			}
			graph[index] = graph[n];
			graph[n] = max;
		}


		int roots[MAX_VEX];  	//根数组,存放各顶点的根节点,以区别是否属于同一个集合
		edge MST[MAX_EDGE];		//存放最小生成树(minimum spanning tree)
		int count = 0;


		for (int n = 0; n < MAX_VEX; n++) {
			roots[n] = -1;
		}

		for (int n = 0; n < MAX_EDGE; n++) {

			if (graph[n].used == 1) {
				int vex_m = find_root(roots, graph[n].edgelink.startpoint);
				int vex_n = find_root(roots, graph[n].edgelink.endpoint);
				if (vex_m != vex_n) {				//如果两者的根节点不同,说明他们属于不同的集合,可以相连
					MST[count] = graph[n].edgelink;//将此边放入MST数组
					count++;
					roots[vex_m] = vex_n;			//将两个树合并,即将顶点vex_n作为vex_m的根节点

				}
				if (count == vex - 1) {
					break;
				}

			}
		}

		for (int k = 0; k < vex - 1; k++) {
//			printf("(%d,%d)%d\n", MST[k].startpoint, MST[k].endpoint, MST[k].weight);   //打印最小生成树

			int start = MST[k].startpoint;
			int end = MST[k].endpoint;

			for (int n = 0; n < 10; n++) {
				drawline(linkside[start][end].starty+n,
				         linkside[start][end].startx,
				         linkside[start][end].endy+n,
				         linkside[start][end].endx, 
					enemy[i].mapv3, 254, enemy[i].targetheight*pixnum, enemy[i].targetwidth*pixnum);
				drawline(linkside[start][end].starty,
					linkside[start][end].startx+n,
					linkside[start][end].endy,
					linkside[start][end].endx+n, 
					enemy[i].mapv3, 254, enemy[i].targetheight*pixnum, enemy[i].targetwidth*pixnum);
				
			}

		}

 

 完整代码



//author @ bilibili 民用级脑的研发记录
// 开发环境 小熊猫c++ 2.25.1  raylib 版本 4.5
// 2024-7-14
// AABB 碰撞检测 在拖拽,绘制,放大缩小中
// 2024-7-20
// 直线改每帧打印一个点,生长的直线,直线炮弹
// 2024-8-4
// 实现敌人追击与敌人死亡与mapv2 敌人轨迹不绘制
#include <raylib.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>


#define MAX_VEX 12
#define MAX_EDGE 144

// 重整原因:解决新函数放大缩小之下,raylib 的网格采样部分,选择数组的一部分刷新倒缓冲区里
// 从直接建立缓冲区,到先在数组里进行移动,然后再设置检查缓冲区
// 最大距离 - 当前坐标,实现坐标系变化,同时对应最顶上,变成新坐标下的最底下,可750-1=749数数得到

// 炮弹
typedef struct lineboom {
	int playeriv2 = 0;						// 一开始发射炮弹的玩家坐标
	int playerjv2 = 0;
	int drawiv2 = 0;						// 发射目标位置坐标
	int drawjv2 = 0;
	int oldx = 0;							// 记录上一格子,用于覆盖旧黑色点,产生炮弹轨迹
	int oldy = 0;
	int atking = 0;							// 是否正在攻击,因为有好几个炮弹,命中之后就结束炮弹运行
	int timev3 = 0;							// 记录运行时间或者长度,到达位置,炮弹爆炸。v3是沿用time,和之前代码变量名字一样
//	int toward = -1;						// 朝向,在剥离代码发现不同朝向,直线代码不同,结束比较符号不同
	int isboom = 0;							// 是否到了爆炸的时机,在修改直线代码中发现的可以合并重复代码,产生的控制变量
} lineboom;
// 随机敌人
typedef struct target {
	int targeti = 0;							// 左上角网格坐标
	int targetj = 0;
	int targetwidth = 0;						// 长宽
	int targetheight = 0;
	int islive = 0;

//	RenderTexture2D* picture;					// 敌人贴图
	RenderTexture2D picture;					// 敌人贴图

	int** oldmap;								// 局部复原数据

	int** mapv3;								// 像素也当成网格,每个记录像素是否能穿过

	target* area;								// 敌人内部的点

	int arealenth;								// 用于记录范围,lenth是半径
} target;
// 边
//typedef struct link {
//	int startx;									// 起点
//	int starty;
//	int endx;									// 终点
//	int endy;
//	int used;									// 是否已经使用
//	int lenth;									// 距离
//
//} link;

// 边
typedef struct edge {
	int startpoint;							// 起点在数组中的序号
	int endpoint;							// 终点在数组中的序号
	int weight;
} edge;
// 边
typedef struct link {
	int startx;									// 起点的坐标
	int starty;
	int endx;									// 终点的坐标
	int endy;
	int used;									// 是否已经使用
	int lenth;									// 距离
	edge edgelink;								// 需要查点,记录所在数组位置
} link;
// 并查集查是否连通
int find_root(int roots[], int n) {
	while (roots[n] != -1) {
		n = roots[n];
	}
	return n;
}

// 检测碰撞,AABB碰撞检测,检测到碰撞时,碰撞产生矩形,左上角的坐标是 bangi j ,碰撞长宽是 bangwidth, bangheight
// 复制粘贴自碰撞检测
int bang(int drawi, int drawj, int mousewidth, int mouseheight, int targeti, int targetj, int targetwidth, int targetheight, int *bangi, int *bangj, int *bangwidth, int *bangheight) {
	int isbang = 0;					// 如果碰撞,就返回1
// +变- i 变 j
	if (drawi >= targeti && targeti >= drawi - mouseheight) {
		// 左上角重叠
		if (targeti - targetheight <= drawi - mouseheight) {
			if (drawj <= targetj && targetj <= drawj + mousewidth) {
				// 左上角重叠
				if (targetj + targetwidth >= drawj + mousewidth) {
//					for (int i = 0; i <  mouseheight - (drawi - targeti) ; i++) {
//						for (int j = 0; j <  mousewidth - ( targetj - drawj); j++) {
//							map[targeti - i][targetj + j] = 2024;
//						}
							map[targeti - i][targetj] = 2024;
//					}
//						for (int j = 0; j <  mousewidth - ( targetj - drawj); j++) {
//							map[targeti][targetj + j] = 2024;
//						}
//					左上角位置
					*bangi = targeti;
					*bangj = targetj;
//					长度,就是注释掉的循环的次数
					*bangwidth = mousewidth - (targetj - drawj);
					*bangheight = -(mouseheight - (drawi - targeti));
					isbang = 1;
				}
				//被包围了
				else if (targetj + targetwidth < drawj + mousewidth) {
//					for (int i = 0; i <  mouseheight - (drawi - targeti) ; i++) {
					map[targeti - i][targetj] = 2024;
//						for (int j = 0; j < targetwidth; j++) {
//							map[targeti - i][targetj + j] = 2024;
//						}
//					}
					*bangi = targeti;
					*bangj = targetj;
					// 注意负号,代表向下
					*bangwidth = targetwidth;
					*bangheight = -(mouseheight - (drawi - targeti));
					isbang = 1;
				}

			} else if (targetj <= drawj && drawj <= targetj + targetwidth) {
				// 右下角重叠
				if (targetj + targetwidth >= drawj + mousewidth) {
//					for (int i = 0; i <  mouseheight - (drawi - targeti) ; i++) {
					map[targeti - i][targetj] = 2024;
//						for (int j = 0; j < mousewidth ; j++) {
//							map[targeti - i][drawj + j] = 2024;
//						}
//					}
					*bangi = targeti;
					*bangj = drawj;
					*bangwidth = mousewidth;
					*bangheight = -(mouseheight - (drawi - targeti));
					isbang = 1;
				}
//			//被包围了
				else if (targetj + targetwidth < drawj + mousewidth) {

//					for (int i = 0; i <  mouseheight - (drawi - targeti) ; i++) {
					map[targeti - i][targetj] = 2024;
//						for (int j = 0; j < targetwidth - (drawj - targetj); j++) {
//							map[targeti - i][drawj + j] = 2024;
//						}
//					}
					*bangi = targeti;
					*bangj = drawj;
					*bangheight = -(mouseheight - (drawi - targeti));
					*bangwidth = targetwidth - (drawj - targetj);
					isbang = 1;
				}
			}
//				for (int i = 0; i <  mouseheight - (drawi - targeti) ; i++) {
//					map[targeti - i][targetj] = 2024;
//				}
		}
		//被包围了
		else if (targeti - targetheight > drawi - mouseheight) {
//				for (int i = 0; i < targetheight; i++) {
//					map[targeti - i][targetj] = 2024;
//				}
			if (drawj <= targetj && targetj <= drawj + mousewidth) {
				// 左上角重叠
				if (targetj + targetwidth >= drawj + mousewidth) {
//					for (int i = 0; i < targetheight; i++) {
							map[targeti - i][targetj] = 2024;
//						for (int j = 0; j <  mousewidth - ( targetj - drawj); j++) {
//							map[targeti - i][targetj + j] = 2024;
//						}
//					}
					*bangi = targeti;
					*bangj = targetj;
					*bangwidth = mousewidth - (targetj - drawj);
					*bangheight = -targetheight;
					isbang = 1;
				}
				//被包围了
				else if (targetj + targetwidth < drawj + mousewidth) {
//					for (int i = 0; i < targetheight; i++) {
							map[targeti - i][targetj] = 2024;
//						for (int j = 0; j < targetwidth; j++) {
//							map[targeti - i][targetj + j] = 2024;
//						}
//					}
					*bangi = targeti;
					*bangj = targetj;
					*bangwidth = targetwidth;
					*bangheight = targetheight;
					isbang = 1;
				}

			} else if (targetj <= drawj && drawj <= targetj + targetwidth) {
				// 右下角重叠
				if (targetj + targetwidth >= drawj + mousewidth) {
//					for (int i = 0; i < targetheight; i++) {
							map[targeti - i][targetj] = 2024;
//						for (int j = 0; j < mousewidth ; j++) {
//							map[targeti - i][drawj + j] = 2024;
//						}
//					}
					*bangi = targeti;
					*bangj = drawj;
					*bangwidth = mousewidth;
					*bangheight = targetheight;
					isbang = 1;
				}
//			//被包围了
				else if (targetj + targetwidth < drawj + mousewidth) {
//					for (int i = 0; i < targetheight; i++) {
							map[targeti - i][targetj] = 2024;
//						for (int j = 0; j < targetwidth - (drawj - targetj); j++) {
//							map[targeti - i][drawj + j] = 2024;
//						}
//					}
					*bangi = targeti;
					*bangj = drawj;
					*bangwidth = targetwidth - (drawj - targetj);
					*bangheight = -targetheight;
					isbang = 1;
				}
			}
		}
	} else if (targeti >= drawi && drawi >= targeti - targetheight) {
		// 被包围了
		if (targeti - targetheight <= drawi - mouseheight) {
//				for (int i = 0; i < mouseheight  ; i++) {
//					map[drawi - i][targetj] = 2024;
//				}
			if (drawj <= targetj && targetj <= drawj + mousewidth) {
				// 左上角重叠
				if (targetj + targetwidth >= drawj + mousewidth) {
//					for (int i = 0; i < mouseheight  ; i++) {
							map[drawi - i][targetj] = 2024;
//						for (int j = 0; j <  mousewidth - ( targetj - drawj); j++) {
//							map[drawi - i][targetj + j] = 2024;
//						}
//					}
					*bangi = drawi;
					*bangj = targetj;
					*bangwidth = mousewidth - ( targetj - drawj);
					*bangheight = -mouseheight;
					isbang = 1;
				}
				//被包围了
				else if (targetj + targetwidth < drawj + mousewidth) {
//					for (int i = 0; i < mouseheight  ; i++) {
							map[drawi - i][targetj] = 2024;
//						for (int j = 0; j < targetwidth; j++) {
//							map[drawi - i][targetj + j] = 2024;
//						}
//					}
					*bangi = drawi;
					*bangj = targetj;
					*bangwidth = targetwidth;
					*bangheight = -mouseheight;
					isbang = 1;
				}

			} else if (targetj <= drawj && drawj <= targetj + targetwidth) {
				// 右下角重叠
				if (targetj + targetwidth >= drawj + mousewidth) {
//					for (int i = 0; i < mouseheight  ; i++) {
							map[drawi - i][targetj] = 2024;
//						for (int j = 0; j < mousewidth ; j++) {
//							map[drawi - i][drawj + j] = 2024;
//						}
//					}
					*bangi = drawi;
					*bangj = drawj;
					*bangwidth = mousewidth;
					*bangheight = -mouseheight;
					isbang = 1;
				}
//			//被包围了
				else if (targetj + targetwidth < drawj + mousewidth) {
//					for (int i = 0; i < mouseheight  ; i++) {
							map[drawi - i][targetj] = 2024;
//						for (int j = 0; j < targetwidth - (drawj - targetj); j++) {
//							map[drawi - i][drawj + j] = 2024;
//						}
//					}
					*bangi = drawi;
					*bangj = drawj;
					*bangwidth = targetwidth - (drawj - targetj);
					*bangheight = -mouseheight;
					isbang = 1;
				}
			}
		}

//			//被包围了
		else if (targeti - targetheight > drawi - mouseheight) {
//			for (int i = 0; i < targetheight - ( targeti - drawi ); i++) {
//				map[drawi - i][targetj] = 2024;
//			}
			if (drawj <= targetj && targetj <= drawj + mousewidth) {
				// 左上角重叠
				if (targetj + targetwidth >= drawj + mousewidth) {
//					for (int i = 0; i < targetheight - ( targeti - drawi ); i++) {
							map[drawi - i][targetj] = 2024;
//						for (int j = 0; j <  mousewidth - ( targetj - drawj); j++) {
//							map[drawi - i][targetj + j] = 2024;
//						}
//					}
					*bangi = drawi;
					*bangj = targetj;
					*bangwidth = mousewidth - ( targetj - drawj);
					*bangheight = -(targetheight - ( targeti - drawi ));
					isbang = 1;
				}
				//被包围了
				else if (targetj + targetwidth < drawj + mousewidth) {
//					for (int i = 0; i < targetheight - ( targeti - drawi ); i++) {
							map[drawi - i][targetj] = 2024;
//						for (int j = 0; j < targetwidth; j++) {
//							map[drawi - i][targetj + j] = 2024;
//						}
//					}
					*bangi = drawi;
					*bangj = targetj;
					*bangwidth = targetwidth;
					*bangheight = -(targetheight - ( targeti - drawi ));
					isbang = 1;
				}

			} else if (targetj <= drawj && drawj <= targetj + targetwidth) {
				// 右下角重叠
				if (targetj + targetwidth >= drawj + mousewidth) {
//					for (int i = 0; i < targetheight - ( targeti - drawi ); i++) {
							map[drawi - i][targetj] = 2024;
//						for (int j = 0; j < mousewidth ; j++) {
							map[drawi - i][drawj + j] = 2024;
//							map[drawi - i][drawj + j] = 2024;
//						}
//					}
					*bangi = drawi;
					*bangj = drawj;
					*bangwidth = mousewidth;
					*bangheight = -(targetheight - ( targeti - drawi ));
					isbang = 1;
				}
//			//被包围了
				else if (targetj + targetwidth < drawj + mousewidth) {
//					for (int i = 0; i < targetheight - ( targeti - drawi ); i++) {
//							map[drawi - i][targetj] = 2024;
//						for (int j = 0; j < targetwidth - (drawj - targetj); j++) {
//							map[drawi - i][drawj + j] = 2024;
//						}
//					}
					*bangi = drawi;
					*bangj = drawj;
					*bangwidth = targetwidth - (drawj - targetj);
					*bangheight = -(targetheight - ( targeti - drawi ));
					isbang = 1;
				}
			}
		}
	}

	if (isbang == 1) {
		return isbang;
	} else {
		return 0;
	}
}



// 直线攻击检测,恢复炮弹个数
void checkend(lineboom* booms, int boomsum, int* have, int** map, int mapi, int mapj) {

	for (int n = 0; n < boomsum; n++) {
		if (booms[n].isboom == 1) {
			for (int i = 0; i < 3; i++) {
				for (int  j = 0; j < 10; j++) {
					// 注意m 增加,数字增加,却是往上增加,所以需要往下走要减
					if (booms[n].drawiv2 - i < 0 || booms[n].drawiv2 - i >= mapi || booms[n].drawjv2 + j < 0 || booms[n].drawjv2 + j >= mapj) {
						break;
					}
					map[booms[n].drawiv2 - i][booms[n].drawjv2 + j] = 1224;
				}
			}

			booms[n].atking = 0;
			booms[n].timev3 = 0;
			booms[n].isboom = 0;
			*have += 1;
		}
	}


}

// 炮弹爆炸
void checkboom(lineboom booms, target* enemy, int** map, int enemysum, int mapi, int mapj) {
	// 直线炮弹碰撞检测
	for (int n = 0; n < enemysum; n++) {
		int bangi = 0;
		int bangj = 0;
		int bangwidth = 0;
		int bangheight = 0;
		// 最小是1,1,这样才绘制一次,此时绘制到炮弹点上
		if (bang(booms.oldy, booms.oldx, 10, 10, enemy[n].targeti, enemy[n].targetj, enemy[n].targetwidth, enemy[n].targetheight, &bangi, &bangj, &bangwidth, &bangheight)) {
			for (int i = 0; i > bangheight; i--) {
				for (int j = 0; j < bangwidth; j++) {
					// m 小于零,因为高度是负数,向下,原因是之前bang 函数代码直接记录符号了,都是向下负数小于零,加一个负数即可
					// 浅蓝色
					if (bangi + i < 0 || bangi + i > mapi || bangj + j < 0 || bangj + j > mapj) {
						break;
					}
					map[bangi + i][bangj + j] = 12;
				}
			}
			// 敌人死亡,这是在敌人移动之后追加的代码
			enemy[n].islive = 0;
//						printf("bang ji width height %d %d %d %d\n", bangj, bangi, bangwidth, bangheight);

		}
	}
}
// 直线炮弹移动攻击
void lineatk(lineboom* booms, int boomsum, int** map) {
	float k = 0;
	for (int n = 0; n < boomsum; n++) {

		// 如果是正在攻击的炮弹
		if (booms[n].atking == 1) {

		} else {
			continue;
		}
		// 如果炮弹已经发射一格
		if (booms[n].timev3 == 0) {

		} else {
			// 用黄色覆盖第一个点
			map[booms[n].oldy][booms[n].oldx] = 224;
		}


		int drawj = booms[n].drawjv2;
		int drawi = booms[n].drawiv2;
		int playeri = booms[n].playeriv2;
		int playerj = booms[n].playerjv2;

//			重整,向东走东北,东南偏
		// 追加两个大小情况
		if (drawj - playerj > 0 &&
		    // >=0 >0 会导致炮弹不能移动,炮弹数目不恢复
		    ((drawi - playeri >= 0 && drawi - playeri <= drawj - playerj)
		     || (drawi - playeri < 0 && (-(drawi - playeri)) <= drawj - playerj))) {

			// 炮弹到达目的地,就爆炸,往东南北偏时
			if (drawj - playerj <= booms[n].timev3) {

				booms[n].isboom = 1;
			}

			// 东北偏
			// 注意大于0
			if (drawi - playeri >= 0 && drawi - playeri <= drawj - playerj) {
				k = (drawi - playeri) / (1.0 * ( drawj - playerj));
				int height = 0;
				float a = 0;
				for (int lenth = 0; lenth < drawj - playerj; lenth++) {
					a = a + k;
					if (a > 1) {
						a -= 1;
						height += 1;
					} else {

					}
//						map[playeri + height][playerj + lenth] = 1949;
//						lenth == (drawj - playerj 改 >=
					if (lenth >= booms[n].timev3 || lenth >= (drawj - playerj)) {
						booms[n].timev3 = lenth + 1;
						map[playeri + height][playerj + lenth] = 1949;
						booms[n].oldy = playeri + height;
						booms[n].oldx = playerj + lenth;
						break;
					}
				}


			}
			//东南偏
			else if (drawi - playeri < 0 && (-(drawi - playeri)) <= drawj - playerj) {
				k = -(drawi - playeri) / (1.0 * ( drawj - playerj));
				int height = 0;
				float a = 0;
				for (int lenth = 0; lenth < drawj - playerj; lenth++) {
					a = a + k;
					if (a > 1) {
						a -= 1;
						height += 1;
					} else {

					}
//						map[playeri + (-height)][playerj + lenth] = 1949;

					if (lenth >= booms[n].timev3 || lenth == (drawj - playerj)) {
						booms[n].timev3 = lenth + 1;
						map[playeri + (-height)][playerj + lenth] = 1949;
						booms[n].oldy = playeri + (- height);
						booms[n].oldx = playerj + lenth;
						break;
					}
				}
			}
		}
		// 向西走西北,西南偏
		else if (drawj - playerj < 0 &&
		         // 注意 == 部分 drawi - playeri <= -(drawj - playerj) 可以等于,这个是斜线
		         ((drawi - playeri >= 0 && drawi - playeri <= -(drawj - playerj))
		          || (drawi - playeri < 0 && (-(drawi - playeri)) <= -(drawj - playerj)))) {
			// 炮弹到达目的地,就爆炸,往西南北偏时

			if (-(drawj - playerj) <= booms[n].timev3) {
				booms[n].isboom = 1;
			}
			// 西北偏
			// 注意drawi - playeri大于0
			if (drawi - playeri >= 0 && drawi - playeri <= -(drawj - playerj)) {
				k = (drawi - playeri) / (1.0 * (-( drawj - playerj)));
				int height = 0;
				float a = 0;
				for (int lenth = 0; lenth < -(drawj - playerj); lenth++) {
					a = a + k;
					if (a > 1) {
						a -= 1;
						height += 1;
					} else {

					}
//						map[playeri + height][playerj + (-lenth)] = 1949;

					if (lenth >= booms[n].timev3 || lenth == -(drawj - playerj)) {
						booms[n].timev3 = lenth + 1;
						map[playeri + height][playerj + (-lenth)] = 1949;
						booms[n].oldy = playeri + height;
						booms[n].oldx = playerj + (-lenth);
						break;
					}
				}

			}
			//西南偏
			else if (drawi - playeri < 0 && (-(drawi - playeri)) <= -(drawj - playerj)) {
				k = -(drawi - playeri) / (1.0 * (-( drawj - playerj)));
				int height = 0;
				float a = 0;
				// 注意在测试检测方位后发现没有增加-号
				for (int lenth = 0; lenth < -(drawj - playerj); lenth++) {
					a = a + k;
					if (a > 1) {
						a -= 1;
						height += 1;
					} else {

					}
//						map[playeri + (-height)][playerj + (-lenth)] = 1949;

					if (lenth >= booms[n].timev3 || lenth == (drawj - playerj)) {
						booms[n].timev3 = lenth + 1;
						map[playeri + (-height)][playerj + (-lenth)] = 1949;
						booms[n].oldy = playeri + (- height);
						booms[n].oldx = playerj + (-lenth);
						break;
					}
				}
			}

		}


//					 重整,向北走东北,西北偏
		if (drawi - playeri > 0 &&
		    ((drawi - playeri > 0 && drawi - playeri > drawj - playerj && drawj - playerj >= 0)
		     || (drawi - playeri > 0 && drawi - playeri > -(drawj - playerj) && drawj - playerj <= 0) )) {

			if (drawi - playeri <= booms[n].timev3) {
				booms[n].isboom = 1;
			}

			// 东北偏
			// 注意大于0

			if (drawi - playeri > 0 && drawi - playeri > drawj - playerj && drawj - playerj >= 0) {
				k = (drawj - playerj) / (1.0 * ( drawi - playeri));
				int height = 0;
				float a = 0;
				for (int lenth = 0; lenth < drawi - playeri; lenth++) {
					a = a + k;
					if (a > 1) {
						a -= 1;
						height += 1;
					} else {

					}
//						map[playeri + lenth][playerj + height] = 1949;
//						lenth == (drawi - playeri 改>= 解决炮弹不回复问题
					if (lenth >= booms[n].timev3 || lenth >= (drawi - playeri)) {
						booms[n].timev3 = lenth + 1;
//							booms[n].timev3 = lenth + 10;
						map[playeri + lenth][playerj + height ] = 1949;
						booms[n].oldy = playeri + lenth;
						booms[n].oldx = playerj + height ;
						break;
					}
				}
			}
			// 西北偏

			// 注意drawi - playeri大于0
//				drawj - playerj <= 0 等于0是竖直的线
			// 发现bug 间距黑色线,改lenth 间隔发现黑色点间距变化
			// 注意垂直部分,大于0,但不是等于0,和西北偏和东北偏如果在一块,会有垂直的黑色间距线
//				if (drawi - playeri > 0 && drawi - playeri > -(drawj - playerj) && drawj - playerj <= 0) {
			if (drawi - playeri > 0 && drawi - playeri > -(drawj - playerj) && drawj - playerj < 0) {
				k = -(drawj - playerj) / (1.0 * ( drawi - playeri));
				int height = 0;
				float a = 0;
				for (int lenth = 0; lenth < drawi - playeri; lenth++) {
					a = a + k;
					if (a > 1) {
						a -= 1;
						height += 1;
					} else {

					}
//						map[playeri + lenth][playerj + (-height)] = 1949;

					if (lenth >= booms[n].timev3 || lenth >= (drawi - playeri)) {
						booms[n].timev3 = lenth + 1;
//							booms[n].timev3 = lenth + 3;
						map[playeri + lenth][playerj + (-height)] = 1949;
						booms[n].oldy = playeri + lenth;
						booms[n].oldx = playerj + (-height);
						break;
					}
				}
//					map[drawi][drawj] = 224;
			}
		}
		// 向南走东南,西南偏
		else if (drawi - playeri < 0 &&
		         ((drawi - playeri < 0 && -(drawi - playeri) > drawj - playerj && drawj - playerj >= 0)
		          || (drawi - playeri < 0 && (-(drawi - playeri)) > -(drawj - playerj) && drawj - playerj <= 0))) {

			if (-(drawi - playeri) <= booms[n].timev3) {
				booms[n].isboom = 1;
			}

			// 东南偏
			// 注意drawi - playeri大于0
			if (drawi - playeri < 0 && -(drawi - playeri) > drawj - playerj && drawj - playerj >= 0) {
				k = (drawj - playerj) / (1.0 * (-( drawi - playeri)));
				int height = 0;
				float a = 0;
				for (int lenth = 0; lenth < -(drawi - playeri); lenth++) {
					a = a + k;
					if (a > 1) {
						a -= 1;
						height += 1;
					} else {

					}
//						map[playeri + (-lenth)][playerj + height] = 1949;

					if (lenth >= booms[n].timev3 || lenth >= -(drawi - playeri)) {
						booms[n].timev3 = lenth + 1;
						map[playeri + (-lenth)][playerj + height ] = 1949;
						booms[n].oldy = playeri + (-lenth);
						booms[n].oldx = playerj + height;
						break;
					}
				}

//					map[drawi][drawj] = 224;
			}
			//西南偏
			else if (drawi - playeri < 0 && (-(drawi - playeri)) > -(drawj - playerj) && drawj - playerj <= 0) {
				k = -(drawj - playerj) / (1.0 * (-( drawi - playeri)));
				int height = 0;
				float a = 0;
				// 注意在测试检测方位后发现没有增加-号
				for (int lenth = 0; lenth < -(drawi - playeri); lenth++) {
					a = a + k;
					if (a > 1) {
						a -= 1;
						height += 1;
					} else {

					}
//						map[playeri + (-lenth)][playerj + (-height)] = 1949;
					if (lenth >= booms[n].timev3 || lenth >= -(drawi - playeri)) {
						booms[n].timev3 = lenth + 1;
						map[playeri + (-lenth)][playerj + (-height)] = 1949;
						booms[n].oldy = playeri + (-lenth);
						booms[n].oldx = playerj + (-height);
						break;
					}
				}
			}

		}
	}
}

void drawline(int drawi, int drawj, int playeri, int playerj, int** map, int sign, int mapi, int mapj) {
	float k = 0;

//			重整,向东走东北,东南偏
	// 追加两个大小情况
	if (drawj - playerj > 0 &&
	    // >=0 >0 会导致炮弹不能移动,炮弹数目不恢复
	    ((drawi - playeri >= 0 && drawi - playeri <= drawj - playerj)
	     || (drawi - playeri < 0 && (-(drawi - playeri)) <= drawj - playerj))) {

		// 东北偏
		// 注意大于0
		if (drawi - playeri >= 0 && drawi - playeri <= drawj - playerj) {
			k = (drawi - playeri) / (1.0 * ( drawj - playerj));
			int height = 0;
			float a = 0;
			for (int lenth = 0; lenth < drawj - playerj; lenth++) {
				a = a + k;
				if (a > 1) {
					a -= 1;
					height += 1;
				} else {
				}
				if (playeri + height >= 0 && playeri + height < mapi && playerj + lenth >= 0 && playerj + lenth < mapj) {
					map[playeri + height][playerj + lenth] = sign;
				}

			}
		}
		//东南偏
		else if (drawi - playeri < 0 && (-(drawi - playeri)) <= drawj - playerj) {
			k = -(drawi - playeri) / (1.0 * ( drawj - playerj));
			int height = 0;
			float a = 0;
			for (int lenth = 0; lenth < drawj - playerj; lenth++) {
				a = a + k;
				if (a > 1) {
					a -= 1;
					height += 1;
				} else {
				}
				if (playeri + (-height) >= 0 && playeri + (-height) < mapi && playerj + lenth >= 0 && playerj + lenth < mapj) {
					map[playeri + (-height)][playerj + lenth] = sign;
				}

			}
		}
	}
	// 向西走西北,西南偏
	else if (drawj - playerj < 0 &&
	         // 注意 == 部分 drawi - playeri <= -(drawj - playerj) 可以等于,这个是斜线
	         ((drawi - playeri >= 0 && drawi - playeri <= -(drawj - playerj))
	          || (drawi - playeri < 0 && (-(drawi - playeri)) <= -(drawj - playerj)))) {
		// 炮弹到达目的地,就爆炸,往西南北偏时

		// 西北偏
		// 注意drawi - playeri大于0
		if (drawi - playeri >= 0 && drawi - playeri <= -(drawj - playerj)) {
			k = (drawi - playeri) / (1.0 * (-( drawj - playerj)));
			int height = 0;
			float a = 0;
			for (int lenth = 0; lenth < -(drawj - playerj); lenth++) {
				a = a + k;
				if (a > 1) {
					a -= 1;
					height += 1;
				} else {
				}
				if (playeri + height >= 0 && playeri + height < mapi && playerj + (-lenth) >= 0 && playerj + (-lenth) < mapi) {
					map[playeri + height][playerj + (-lenth)] = sign;
				}
			}
		}
		//西南偏
		else if (drawi - playeri < 0 && (-(drawi - playeri)) <= -(drawj - playerj)) {
			k = -(drawi - playeri) / (1.0 * (-( drawj - playerj)));
			int height = 0;
			float a = 0;
			// 注意在测试检测方位后发现没有增加-号
			for (int lenth = 0; lenth < -(drawj - playerj); lenth++) {
				a = a + k;
				if (a > 1) {
					a -= 1;
					height += 1;
				} else {
				}
				if (playeri + (-height) >= 0 && playeri + (-height) < mapi && playerj + (-lenth) >= 0 && playerj + (-lenth) < mapj) {
					map[playeri + (-height)][playerj + (-lenth)] = sign;
				}
			}
		}
	}

//					 重整,向北走东北,西北偏
	if (drawi - playeri > 0 &&
	    ((drawi - playeri > 0 && drawi - playeri > drawj - playerj && drawj - playerj >= 0)
	     || (drawi - playeri > 0 && drawi - playeri > -(drawj - playerj) && drawj - playerj <= 0) )) {

		// 东北偏
		// 注意大于0
		if (drawi - playeri > 0 && drawi - playeri > drawj - playerj && drawj - playerj >= 0) {
			k = (drawj - playerj) / (1.0 * ( drawi - playeri));
			int height = 0;
			float a = 0;
			for (int lenth = 0; lenth < drawi - playeri; lenth++) {
				a = a + k;
				if (a > 1) {
					a -= 1;
					height += 1;
				} else {
				}
				if (playeri + lenth >= 0 && playeri + lenth < mapi && playerj + height >= 0 && playerj + height < mapj) {
					map[playeri + lenth][playerj + height] = sign;
				}
			}
		}
		// 西北偏

		// 注意drawi - playeri大于0
//				drawj - playerj <= 0 等于0是竖直的线
		// 发现bug 间距黑色线,改lenth 间隔发现黑色点间距变化
		// 注意垂直部分,大于0,但不是等于0,和西北偏和东北偏如果在一块,会有垂直的黑色间距线
//				if (drawi - playeri > 0 && drawi - playeri > -(drawj - playerj) && drawj - playerj <= 0) {
		if (drawi - playeri > 0 && drawi - playeri > -(drawj - playerj) && drawj - playerj < 0) {
			k = -(drawj - playerj) / (1.0 * ( drawi - playeri));
			int height = 0;
			float a = 0;
			for (int lenth = 0; lenth < drawi - playeri; lenth++) {
				a = a + k;
				if (a > 1) {
					a -= 1;
					height += 1;
				} else {

				}
				if (playeri + lenth >= 0 && playeri + lenth < mapi && playerj + (-height) >= 0 && playerj + (-height) < mapj) {
					map[playeri + lenth][playerj + (-height)] = sign;
				}

			}
		}
	}
	// 向南走东南,西南偏
	else if (drawi - playeri < 0 &&
	         ((drawi - playeri < 0 && -(drawi - playeri) > drawj - playerj && drawj - playerj >= 0)
	          || (drawi - playeri < 0 && (-(drawi - playeri)) > -(drawj - playerj) && drawj - playerj <= 0))) {

		// 东南偏
		// 注意drawi - playeri大于0
		if (drawi - playeri < 0 && -(drawi - playeri) > drawj - playerj && drawj - playerj >= 0) {
			k = (drawj - playerj) / (1.0 * (-( drawi - playeri)));
			int height = 0;
			float a = 0;
			for (int lenth = 0; lenth < -(drawi - playeri); lenth++) {
				a = a + k;
				if (a > 1) {
					a -= 1;
					height += 1;
				} else {

				}
				if (playeri + (-lenth) >= 0 && playeri + (-lenth) < mapi && playerj + height >= 0 && playerj + height < mapj) {
					map[playeri + (-lenth)][playerj + height] = sign;
				}

			}

		}
		//西南偏
		else if (drawi - playeri < 0 && (-(drawi - playeri)) > -(drawj - playerj) && drawj - playerj <= 0) {
			k = -(drawj - playerj) / (1.0 * (-( drawi - playeri)));
			int height = 0;
			float a = 0;
			// 注意在测试检测方位后发现没有增加-号
			for (int lenth = 0; lenth < -(drawi - playeri); lenth++) {
				a = a + k;
				if (a > 1) {
					a -= 1;
					height += 1;
				} else {

				}
				if (playeri + (-lenth) >= 0 && playeri + (-lenth) < mapi && playerj + (-height) >= 0 && playerj + (-height) < mapj) {
					map[playeri + (-lenth)][playerj + (-height)] = sign;
				}

			}
		}
	}
}


int main() {


	int boomsum;
	boomsum = 100;

	// 炮弹数目记录
	int have = boomsum;
	// 我方直线炮弹
	lineboom* booms = new lineboom[boomsum];
	for (int i = 0; i < boomsum; i++) {
		booms[i].playeriv2 = 0;
		booms[i].playerjv2 = 0;
		booms[i].drawiv2 = 0;
		booms[i].drawjv2 = 0;
		booms[i].oldx = 0;
		booms[i].oldy = 0;
		booms[i].timev3 = 0;
		booms[i].atking = 0;
		booms[i].isboom = 0;
	}

	// 敌人的炮弹爆炸
	int boomsumv2 = 100;
	int havev2 = 100;
	// 敌人发射的直线炮弹
	lineboom* boomsv2 = new lineboom[boomsumv2];
	for (int i = 0; i < boomsumv2; i++) {
		boomsv2[i].playeriv2 = 0;
		boomsv2[i].playerjv2 = 0;
		boomsv2[i].drawiv2 = 0;
		boomsv2[i].drawjv2 = 0;
		boomsv2[i].oldx = 0;
		boomsv2[i].oldy = 0;
		boomsv2[i].timev3 = 0;
		boomsv2[i].atking = 0;
		boomsv2[i].isboom = 0;
	}


	int pixnum;
	// 屏幕显示的方格个数
	int showi;
	int showj;
//	比屏幕多出的边距
	int side;																// 可变边距测试成功
	// 一个缓冲区的大小
	int bkmeshmapmaxi;
	int bkmeshmapmaxj;
	int bkmeshwidth;
	int bkmeshheight;
//	一个游戏地图的大小
	int mapi;
	int mapj;

//	pixnum = 30;
//	pixnum = 15;															// mesh中一个网格正方形的边长
//	pixnum = 64;															// mesh中一个网格正方形的边长
//	pixnum = 130;															// mesh中一个网格正方形的边长
	pixnum = 30;															// mesh中一个网格正方形的边长
//	pixnum = 3;																// mesh中一个网格正方形的边长
	int pixnumv2;
// 显示区的网格大小,是沿用之前的pixnum但是自己设定也没问题,于是产生新的变量,
//	其实是测试pixnum对帧率影响,结果发现是drawi j 影响大
	pixnumv2 = 30;

//	30*100大小测试结果
	// 参数:核显 41帧
//	Renderer: Intel(R) Iris(R) Xe Graphics
//	INFO:     > Version:  3.3.0 - Build 31.0.101.4502
//	INFO:     > GLSL:     3.30 - Build 31.0.101.4502

//	RTX3060 57帧,被遮挡47帧率
//	> Vendor:   NVIDIA Corporation
//	INFO:     > Renderer: NVIDIA GeForce RTX 3060 Laptop GPU/PCIe/SSE2
//	INFO:     > Version:  3.3.0 NVIDIA 512.78
//	INFO:     > GLSL:     3.30 NVIDIA via Cg compiler


//	showi = 30;
//	showj = 30;
//	showi = 600;
//	showj = 600;
//	showi = 150;
//	showj = 150;
//	showi = 200;
//	showj = 200;
//	showi = 100;												// 测试破案了,单个瓦片刷新没有影响,但是绘制Draw Texture 是主要限制,100*100每个循环,改pixnum不影响
//	showj = 100;
//	showi = 500;												// 测试破案了,单个瓦片刷新没有影响,但是绘制Draw Texture 是主要限制,100*100每个循环,改pixnum不影响
//	showj = 500;
//	showi = 1500;
//	showj = 1500;
//	showi = 1000;
//	showj = 1000;
//	showi = 1100;												// 1500*1500 1200*1200 超GPU显存了
//	showj = 1100;
	// 注意刷新规模上限70帧下,最多每帧发送100*100的绘制小正方形瓦片,密度是100*100/(1000*1000) =1/100=1%的平均密度
//	showi = 1000;												// 1000*1000*30*30 像素个数是界限了
//	showj = 1000;
//	showi = 100;												// 1000*1000*30*30 像素个数是界限了
//	showj = 100;
//	showi = 30;													// 1000*1000*30*30 像素个数是界限了
//	showj = 30;
//	showi = 1000;												// 测试大地图碰撞检测
//	showj = 1000;
	showi = 1001;												// 测试大地图碰撞检测
	showj = 1001;
//	150 50+帧率 99%GPU 82°C
//	还是100
//	showi = 150;
//	showj = 150;
//	showi = 10;													// 测试破案了,单个瓦片刷新没有影响,但是绘制Draw Texture 是主要限制,100*100每个循环,改pixnum不影响
//	showj = 10;
//	showi = 200;												// 测试破案了,单个瓦片刷新没有影响,但是绘制Draw Texture 是主要限制,100*100每个循环,改pixnum不影响
//	showj = 200;
//	去除刷新检测,可以100 持续57帧率
//	side=20;
//	side = showj*0.2;
//	side = 0;
//	side = 10;													// 绘制四个角的红白矩形抖动,原因是 后面的 if对draftx进行平移,平移后采样区域回到靠左或靠右,出现复位
//	side = 1;
//	side = 1;													// while 边界检测+1解决+0导致的死循环允许side=0
//	side = 1;													// while 边界检测+1解决+0导致的死循环允许side=0 改完由于偏移于是不准确了,又拒绝了+1,于是不能设置为0,保留窗口抖动
//	side = 10;													// while 边界检测+1解决+0导致的死循环允许side=0 改完由于偏移于是不准确了,又拒绝了+1,于是不能设置为0,保留窗口抖动,但是拒绝边界检测又测试允许0
	side = 0;
	if (showi * showj > 100 * 100) {							// 如果超出GPU网格刷新界限就变成单宫格模式
		side = 0;
	} else {
		side = 1;
	}
	// while 边界检测+1解决+0导致的死循环允许side=0 改完由于偏移于是不准确了,又拒绝了+1,于是不能设置为0,保留窗口抖动,但是拒绝边界检测又测试允许0
//	修正,原来是由于绘制GPU画布采样界限,多余部分会自动镜像绘制,数组越界却没有发生
//	再解释,破案了,数组越界但是没闪退,又有边界检测结果采样不会采样到出界部分。
//	于是增加边界检测

//	边界处理
	bkmeshmapmaxi = side + showi + side;								// 象形表示,左右各有这样的边距
	bkmeshmapmaxj = side + showj + side;
	bkmeshwidth = bkmeshmapmaxj * pixnum;								// 用于瓦片刷新
	bkmeshheight = bkmeshmapmaxi * pixnum;

//	mapi = bkmeshmapmaxi * 20;
//	mapj = bkmeshmapmaxj * 20;
	//测试边界
//	mapi = bkmeshmapmaxi * 1;
//	mapj = bkmeshmapmaxj * 1;
//	mapi = bkmeshmapmaxi * 2;
//	mapj = bkmeshmapmaxj * 2;
//	mapi = bkmeshmapmaxi * 20;
//	mapj = bkmeshmapmaxj * 20;

	// 加上else 出现黑边BUG
//	if (side == 0) {
//		mapi = bkmeshmapmaxi * 1;					// side=0 则只有一个宫格
//		mapj = bkmeshmapmaxj * 1;
//	} else {
//		mapi = bkmeshmapmaxi * 20;
//		mapj = bkmeshmapmaxj * 20;
//	}

	if (side == 0) {
		mapi = bkmeshmapmaxi * 1;					// side=0 则只有一个宫格
		mapj = bkmeshmapmaxj * 1;
	} else {
		mapi = bkmeshmapmaxi * 5;
		mapj = bkmeshmapmaxj * 5;
	}

	int **map;
	int **meshmap;
	int maxgamex;									// 允许的最大位置
	int maxgamey;

	int** mapv2;									// 解决敌人轨迹覆盖地图

	target* region;								// 记录像素玩家所在区域,在哪个敌人区域上,用于减少比较,性能优化
	region = NULL;
	int regionflag = 0;								// 不在区域里
	// 回滚代码,原因是采样区没法修改罢了
//	maxgamey = mapi * 30 - showi * 30;					// 左上角拖拽距离游戏边界差一个背景采样区大小
//	maxgamex = mapj * 30 - showj * 30;
	maxgamey = mapi * pixnum - showi * pixnum;			// 左上角拖拽距离游戏边界差一个背景采样区大小
	maxgamex = mapj * pixnum - showj * pixnum;
	// 但是发现可以修改粘贴的大小
	int showiv2;									// 解决showi,j导致显示不全,边距变化后,检测限制的BUG
	int showjv2;
//	showiv2 = 30;
//	showjv2 = 30;
	showiv2 = 40;
	showjv2 = 60;
	//	记录bkmeshmap 网格,用于出界刷新
	int bkmeshmapi;
	int bkmeshmapj;
	bkmeshmapi = 0;
//	bkmeshmapi = 0;									// 解决黑边BUG 原来是复制粘贴初始化重复了导致没初始化,对应在后面的参考点变化
	bkmeshmapj = 0;

	//	拖拽边界
	int limitleft;
	int limittop;

//	坐标系变化,现在是在底部进行,左下角是0,0原点
	limitleft = 0;
	limittop = 0;


	map = new int*[mapi];
	for (int i = 0; i < mapi; i++) {
		map[i] = new int[mapj];
	}
	for (int i = 0; i < mapi; i++) {
		for (int j = 0; j < mapj; j++) {
			map[i][j] = (j + i) % 27;					// 测试数据,渐变 25改105 柔和
		}
	}
	//	测试边界
	for (int j = 0; j < mapj; j++) {
		map[0][j] = 9999;
		map[mapi - 1][j] = 9999;
	}
	for (int i = 0; i < mapi; i++) {
		map[i][0] = 9999;
		map[i][mapj - 1] = 9999;
	}
	meshmap = new int*[bkmeshmapmaxi];
	for (int i = 0; i < bkmeshmapmaxi; i++) {
		meshmap[i] = new int[bkmeshmapmaxj];
	}
	for (int i = 0; i < bkmeshmapmaxi; i++) {
		for (int j = 0; j < bkmeshmapmaxj; j++) {
			meshmap[i][j] = -1;
		}
	}


	mapv2 = new int*[mapi];
	for (int i = 0; i < mapi; i++) {
		mapv2[i] = new int[mapj];
	}

	for (int i = 0; i < mapi; i++) {
		for (int j = 0; j < mapj; j++) {
			mapv2[i][j] = map[i][j];
		}
	}

	// 目标个数
	int enemysum;
//	enemysum=20;
//	enemysum=100;				// 100 个就闪退,原来是敌人绘制网格出界,这是在鼠标点击炮弹击中边界闪退得到的
//	enemysum=50;
//	enemysum=150;
//	enemysum = 50;
//	enemysum = 250;
	enemysum = 50;
	// 随机数查的方法,_time64 获取时间,srand设置随机数种子

	// 这俩都行,保证每次开机都不一样
//	SetRandomSeed((unsigned)_time64(NULL));
	srand((unsigned)_time64(NULL));

//	a = rand();

	int enemylive;

	enemylive = enemysum;			// 存活敌人个数,用于敌人死亡不立即刷新

	target* enemy = new target[enemysum];
	for (int i = 0; i < enemysum; i++) {
		enemy[i].islive = 1;
		enemy[i].targeti = GetRandomValue(0, mapi - 1);
		enemy[i].targetj = GetRandomValue(0, mapj - 1);
		enemy[i].targetwidth = GetRandomValue(10, 20);
		enemy[i].targetheight = GetRandomValue(10, 20);

		// 敌人随机贴图
		// 在3. 测试Texture 之后发现需要在Initwindows 之后使用,原因是上下文Opengl 还没设置
//		enemy[i].picture = new RenderTexture2D();
//		enemy[i].picture =  LoadRenderTexture(enemy[i].targetwidth * pixnum, enemy[i].targetheight * pixnum);
//		RenderTexture mesh = LoadRenderTexture(enemy[i].targetwidth * pixnum, enemy[i].targetheight * pixnum);
//		enemy[i].picture = &mesh;

//		enemy[i].picture = LoadRenderTexture(enemy[i].targetwidth , enemy[i].targetheight );

//		BeginTextureMode(enemy[i].picture);
//		for (int y = 0; y < enemy[i].targetheight * pixnum; y++) {
//			for (int x = 0; x < enemy[i].targetwidth * pixnum; x++) {
//				DrawPixel(x, y, {x%255, y%255, x * y%255, 255});
//			}
//		}
//		EndTextureMode();

		// 记录采样数据,用于恢复网格地图,覆盖旧贴图
		enemy[i].oldmap = new int*[100];
		for (int n = 0; n < 100; n++) {
			enemy[i].oldmap[n] = new int[100];
		}
		for (int n = 0; n < enemy[i].targetheight; n++) {
			for (int m = 0; m < enemy[i].targetwidth; m++) {
//				enemy[i].oldmap[n][m] = map[enemy[i].targeti - n][enemy[i].targetj + m];
				// 追加边界检测,解决闪退问题
				if (enemy[i].targeti - n >= 0 && enemy[n].targeti - n < mapi && enemy[i].targetj + m >= 0 && enemy[i].targetj + m < mapj) {
					enemy[i].oldmap[n][m] = map[enemy[i].targeti - n][enemy[i].targetj + m];
				}
			}
		}

		// 记录局部区域像素网格
		enemy[i].mapv3 = new int*[1000];
		for (int n = 0; n < 1000; n++) {
			enemy[i].mapv3[n] = new int[1000];
		}

		for (int n = 0; n < enemy[i].targetheight * pixnum; n++) {
			for (int m = 0; m < enemy[i].targetwidth * pixnum; m++) {
//				enemy[i].mapv3[n][m] = (m + n) % 255;
//				enemy[i].mapv3[n][m] = (m + n) % 250;						// 254是白色,用于绘制房间,黑色覆盖时,不覆盖白色
				enemy[i].mapv3[n][m] = 0;						// 254是白色,用于绘制房间,黑色覆盖时,不覆盖白色
			}
		}

//		生成入口
		enemy[i].area = new target[100];
		int choose = GetRandomValue(1, 4);	//随机四个方向选一个方向
//		int choose = 4;
		enemy[i].area[0].targetwidth = GetRandomValue(36, 50);									// 先长宽
		enemy[i].area[0].targetheight = GetRandomValue(30, 50);
		enemy[i].area[0].arealenth = 0;														// 设置距离很大
		if (choose == 1) {																		// 东边,最右边产生一个区域,可以当成入口
//			enemy[i].area[0].targetwidth = GetRandomValue(6, 20);								// 先长宽
//			enemy[i].area[0].targetheight = GetRandomValue(10, 20);
			enemy[i].area[0].targetj = enemy[i].targetwidth * pixnum - enemy[i].area[0].targetwidth;										// 再坐标,防止越界
			enemy[i].area[0].targeti = GetRandomValue(0, enemy[i].targetheight * pixnum - enemy[i].area[0].targetheight);
		} else if (choose == 2) {																							// 北边,上边
//			enemy[i].area[0].targetj = enemy[i].targetj;
//			enemy[i].area[0].targeti = enemy[i].targeti;
			enemy[i].area[0].targetj = GetRandomValue(0, enemy[i].targetwidth * pixnum - enemy[i].area[0].targetwidth);										// 再坐标,防止越界
			enemy[i].area[0].targeti = 0;

		} else if (choose == 3) {																								// 西边
			enemy[i].area[0].targetj = 0;
			enemy[i].area[0].targeti = GetRandomValue(0, enemy[i].targetheight * pixnum - enemy[i].area[0].targetheight);

		} else if (choose == 4) {																								// 南边
			enemy[i].area[0].targetj = GetRandomValue(0, enemy[i].targetwidth * pixnum - enemy[i].area[0].targetwidth);
			enemy[i].area[0].targeti = enemy[i].targetheight * pixnum - enemy[i].area[0].targetheight;
		}

		link** linkside = new link*[110];

		for (int i = 0; i < 110; i++) {
			linkside[i] = new link[110];
		}

		for (int i = 0; i < 110; i++) {
			for (int j = 0; j < 110; j++) {
				linkside[i][j].used = 1;
			}
		}

		for (int n = 1; n <= 10; n++) {
			enemy[i].area[n].targetwidth = GetRandomValue(30, 50);									// 先长宽
			enemy[i].area[n].targetheight = GetRandomValue(30, 50);
			enemy[i].area[n].targetj = GetRandomValue(0, enemy[i].targetwidth * pixnum - enemy[i].area[n].targetwidth);
			enemy[i].area[n].targeti = GetRandomValue(0, enemy[i].targetheight * pixnum - enemy[i].area[n].targetheight);
		}

		// 生成出口
		int check = 1;
		int minlenth = 99999;
		int goal = 0;
		choose = GetRandomValue(1, 4);	//随机四个方向选一个方向
		enemy[i].area[11].targetwidth = GetRandomValue(30, 50);									// 先长宽
		enemy[i].area[11].targetheight = GetRandomValue(30, 50);
		if (choose == 1) {																		// 东边,最右边产生一个区域,可以当成入口
//			enemy[i].area[0].targetwidth = GetRandomValue(6, 20);								// 先长宽
//			enemy[i].area[0].targetheight = GetRandomValue(10, 20);
			enemy[i].area[11].targetj = enemy[i].targetwidth * pixnum - enemy[i].area[11].targetwidth;										// 再坐标,防止越界
			enemy[i].area[11].targeti = GetRandomValue(0, enemy[i].targetheight * pixnum - enemy[i].area[11].targetheight);
		} else if (choose == 2) {																							// 北边,上边
//			enemy[i].area[0].targetj = enemy[i].targetj;
//			enemy[i].area[0].targeti = enemy[i].targeti;
			enemy[i].area[11].targetj = GetRandomValue(0, enemy[i].targetwidth * pixnum - enemy[i].area[11].targetwidth);										// 再坐标,防止越界
			enemy[i].area[11].targeti = 0;

		} else if (choose == 3) {																								// 西边
			enemy[i].area[11].targetj = 0;
			enemy[i].area[11].targeti = GetRandomValue(0, enemy[i].targetheight * pixnum - enemy[i].area[11].targetheight);

		} else if (choose == 4) {																								// 南边
			enemy[i].area[11].targetj = GetRandomValue(0, enemy[i].targetwidth * pixnum - enemy[i].area[11].targetwidth);
			enemy[i].area[11].targeti = enemy[i].targetheight * pixnum - enemy[i].area[11].targetheight;
		}

//		增加数据

		for (int n = 0; n <= 11; n++) {
			for (int m = 0; m <= 11; m++) {
				int startx = enemy[i].area[n].targetj;
				int starty = enemy[i].area[n].targeti;
				int endx = enemy[i].area[m].targetj;
				int endy = enemy[i].area[m].targeti;
				linkside[n][m].startx = enemy[i].area[n].targetj;
				linkside[n][m].starty = enemy[i].area[n].targeti;
				linkside[n][m].endx = enemy[i].area[m].targetj;
				linkside[n][m].endy = enemy[i].area[m].targeti;
				linkside[n][m].used = 0;
				if (n == m) {
					linkside[n][m].used = 1;
//					linkside[n][m].lenth=999999;
//					linkside[n][m].edgelink.weight=999999;
				} else {
					linkside[n][m].lenth = sqrt((startx - endx) * (startx - endx) + (starty - endy) * (starty - endy));
				}

//				printf("%d\n",linkside[n][m].lenth);

			}
//			printf("%d %d\n",linkside[n][0].startx,linkside[n][0].starty);
		}




//		for (int n = 0; n < 11; n++) {
//			int goal = 2;
//			int lenth = 999999;
//
//			// 找当前最小边
//			for (int m = 0; m < 11; m++) {
//				if (linkside[n][m].used == 1) {
//
//				} else {
//					if (linkside[n][m].lenth < lenth) {
//						lenth = linkside[n][m].lenth;
//						goal = m;
//					}
//				}
//			}
//
//			// 连线
//			for (int m = 0; m < 10; m++) {
//				drawline(linkside[n][goal].starty + m, linkside[n][goal].startx, linkside[n][goal].endy + m, linkside[n][goal].endx, enemy[i].mapv3, 254, enemy[i].targetheight * pixnum, enemy[i].targetwidth * pixnum);
//				drawline(linkside[n][goal].starty, linkside[n][goal].startx + m, linkside[n][goal].endy, linkside[n][goal].endx + m, enemy[i].mapv3, 254, enemy[i].targetheight * pixnum, enemy[i].targetwidth * pixnum);
				drawline(0,0, 550,550,enemy[i].mapv3, 254, enemy[i].targetheight*pixnum, enemy[i].targetwidth*pixnum);
//
//			}
//			linkside[n][goal].used = 1;					// 连完的线
			linkside[goal][n].used = 1;
//		}




//		link linkside[12][12];			// 兼容之前参数
		int vex = 12;					//顶点个数
		int edgeside = 12 * 12;			//边个数

		link graph[MAX_EDGE];
		edge graphv2[MAX_EDGE];

		/*
		//	for (int k = 0; k < edgeside; k++) {
		//		for (int n = 0; n <= 11; n++) {
		//			for (int m = 0; m <= 11; m++) {
		//				if (linkside[n][m].used == 0) {
		//					graph[k].startx = linkside[n][m].startx;
		//					graph[k].starty = linkside[n][m].starty;
		//					graph[k].endx = linkside[n][m].endx;
		//					graph[k].endy = linkside[n][m].endy;
		//					graph[k].lenth = linkside[n][m].lenth;
		//					graph[k].used = 1;
		//
		//					graphv2[k].startpoint=n;
		//					graphv2[k].endpoint=m;
		//					graph[k].lenth=linkside[n][m].lenth;
		//				}
		//			}
		//		}
		//	}
		*/

		for (int n = 0; n < 144; n++) {
			graph[n].used = 0;
		}
//
		int k = 0;
		for (int n = 0; n <= 11; n++) {
			for (int m = 0; m <= 11; m++) {
				if (linkside[n][m].used == 0) {

					graph[k].startx = linkside[n][m].startx;
					graph[k].starty = linkside[n][m].starty;
					graph[k].endx = linkside[n][m].endx;
					graph[k].endy = linkside[n][m].endy;
					graph[k].lenth = linkside[n][m].lenth;
					graph[k].used = 1;

					graph[k].edgelink.startpoint = n;
					graph[k].edgelink.endpoint = m;
					graph[k].edgelink.weight = linkside[n][m].lenth;
					k++;
				}
			}
		}

//	标记不用数据
		for (int n = 0; n < MAX_EDGE; n++) {
			if (graph[n].used == 0) {
				graph[n].lenth = 999999;
				graph[n].edgelink.weight = 999999;
			}
		}

		// 插入排序
		link max;
		int index;
		for (int n = 0; n < MAX_EDGE; n++) {
			index = n;
			max = graph[n];
			for (int m = n + 1; m < MAX_EDGE; m++) {
				if (graph[m].lenth < max.lenth) {
					max = graph[m];
					index = m;
				}
			}
			graph[index] = graph[n];
			graph[n] = max;
		}


		int roots[MAX_VEX];  	//根数组,存放各顶点的根节点,以区别是否属于同一个集合
		edge MST[MAX_EDGE];		//存放最小生成树(minimum spanning tree)
		int count = 0;


		for (int n = 0; n < MAX_VEX; n++) {
			roots[n] = -1;
		}

		for (int n = 0; n < MAX_EDGE; n++) {

			if (graph[n].used == 1) {
				int vex_m = find_root(roots, graph[n].edgelink.startpoint);
				int vex_n = find_root(roots, graph[n].edgelink.endpoint);
				if (vex_m != vex_n) {				//如果两者的根节点不同,说明他们属于不同的集合,可以相连
					MST[count] = graph[n].edgelink;//将此边放入MST数组
					count++;
					roots[vex_m] = vex_n;			//将两个树合并,即将顶点vex_n作为vex_m的根节点

				}
				if (count == vex - 1) {
					break;
				}

			}
		}

		for (int k = 0; k < vex - 1; k++) {
//			printf("(%d,%d)%d\n", MST[k].startpoint, MST[k].endpoint, MST[k].weight);   //打印最小生成树

			int start = MST[k].startpoint;
			int end = MST[k].endpoint;

			for (int n = 0; n < 10; n++) {
				drawline(linkside[start][end].starty+n,
				         linkside[start][end].startx,
				         linkside[start][end].endy+n,
				         linkside[start][end].endx, 
					enemy[i].mapv3, 254, enemy[i].targetheight*pixnum, enemy[i].targetwidth*pixnum);
				drawline(linkside[start][end].starty,
					linkside[start][end].startx+n,
					linkside[start][end].endy,
					linkside[start][end].endx+n, 
					enemy[i].mapv3, 254, enemy[i].targetheight*pixnum, enemy[i].targetwidth*pixnum);
				
			}

		}






		// 绘制区域
		// 注意是等于11,第十二个
		for (int n = 0; n <= 11; n++) {
			for (int x = 0; x < enemy[i].area[n].targetwidth; x++) {
				for (int y = 0; y < enemy[i].area[n].targetheight; y++) {
//					0<= 漏掉等号导致最顶上像素没覆盖,以为是数组对应错位
					if (0 <= enemy[i].area[n].targeti + y
					    && enemy[i].area[n].targeti  + y < enemy[i].targetheight * pixnum
					    && 0 <= enemy[i].area[n].targetj + x
					    && enemy[i].area[n].targetj + x < enemy[i].targetwidth * pixnum) {
						enemy[i].mapv3[enemy[i].area[n].targeti + y][enemy[i].area[n].targetj + x] = 254;
					}
				}
			}
		}

	}


	// 随便一个敌人记录为所在地区,只是为了不让region为空,减少比较
	region = &enemy[0];

//	enemy[0].picture = LoadRenderTexture(50,50);

	// 绘制敌人
	for (int n = 0; n < enemysum; n++) {
		for (int i = 0; i < enemy[n].targetheight; i++) {
			for (int j = 0; j < enemy[n].targetwidth; j++) {
				// 发现是没有越界检测所以导致100 个时,碰到边界闪退
				if (enemy[n].targeti - i < 0 || enemy[n].targeti - i >= mapi || enemy[n].targetj + j < 0 || enemy[n].targetj + j >= mapj) {
					break;
				} else {
					map[enemy[n].targeti - i][enemy[n].targetj + j] = 1;
				}

			}
		}
	}




//	初始化窗口
//	InitWindow(1750, 1050, "test for location");
//	InitWindow(300+showiv2*pixnumv2, 300+showjv2*pixnumv2, "test for location");
	InitWindow(showjv2 * pixnumv2, showiv2 * pixnumv2, "test for location");
//	设置GPU可以操作的画布,一定要再初始化窗口之后才行,实际上是OpenGL的上下文,或者说默认环境设置
	RenderTexture2D mesh = LoadRenderTexture(bkmeshmapmaxi * pixnum, bkmeshmapmaxj * pixnum);

	// 这俩可以追加敌人贴图
	for (int n = 0; n < enemysum; n++) {
		enemy[n].picture = LoadRenderTexture(enemy[n].targetwidth * pixnum, enemy[n].targetheight * pixnum);
		BeginTextureMode(enemy[n].picture);
		for (int y = 0; y < enemy[n].targetheight * pixnum; y++) {
			for (int x = 0; x < enemy[n].targetwidth * pixnum; x++) {
//				DrawPixel(x, y, {x % 255, y % 255, x * y % 255, 255});
				// 数组增加后,是从下往上绘制,从下往上打印,数组对应从0到999
//				DrawPixel(x, y, {enemy[n].mapv3[y][x], enemy[n].mapv3[y][x], enemy[n].mapv3[y][x], 255});
				// 重新测试边界,查坐标系,看数组和像素是否对应
				if (enemy[n].mapv3[y][x] == 254) {
					DrawPixel(x, y, {enemy[n].mapv3[y][x], enemy[n].mapv3[y][x], enemy[n].mapv3[y][x], 255});
				} else if (y == 0) {
					DrawPixel(x, y, {0, 255, 255, 255});
				} else {
					DrawPixel(x, y, {enemy[n].mapv3[y][x], enemy[n].mapv3[y][x], enemy[n].mapv3[y][x], 255});
				}


			}
		}
		EndTextureMode();
	}

	// 设置缩放过滤器模式
	// 查找raylib.h得到
//	SetTextureFilter(mesh.texture,TEXTURE_FILTER_ANISOTROPIC_16X);			// 缩小,帧率会下降到50+

	// 这两个带明暗了
//	GenTextureMipmaps(&mesh.texture);                               //为Texture生成GPU mipmap
//	https://www.cnblogs.com/wuyuan2011woaini/p/15655883.html
//	SetTextureFilter(mesh.texture,TEXTURE_FILTER_TRILINEAR);		// 线性滤波

//	GenTextureMipmaps(&mesh.texture);                               //为Texture生成GPU mipmap
//	各向异性过滤
//	SetTextureFilter(mesh.texture,TEXTURE_FILTER_ANISOTROPIC_16X);

//	https://www.cnblogs.com/wuyuan2011woaini/p/15655883.html
//	SetTextureFilter(mesh.texture,TEXTURE_FILTER_TRILINEAR);			// 单独一行,没有mipmap就不是缩小变暗
//	SetTextureFilter(mesh.texture,TEXTURE_FILTER_POINT);				// 无滤波
//	SetTextureFilter(mesh.texture, TEXTURE_FILTER_BILINEAR);			// 线性滤波
	SetTextureFilter(mesh.texture, TEXTURE_FILTER_POINT);				// 无滤波

//	如果渲染器超出原始边界范围,则会复制边缘颜色对超出范围的区域进行着色
//	SetTextureWrap(mesh.texture,TEXTURE_WRAP_CLAMP);					// 这个相对于出界拉伸
//	SetTextureWrap(mesh.texture,TEXTURE_WRAP_REPEAT);					// 这个是默认的,也就是没有这一行命令也和之前一样
//	SetTextureWrap(mesh.texture,TEXTURE_WRAP_MIRROR_REPEAT);				// 这个是镜像出界
//	SetTextureWrap(mesh.texture,TEXTURE_WRAP_MIRROR_CLAMP);					// 这个是镜像出界,边线拉伸
	SetTextureWrap(mesh.texture, TEXTURE_WRAP_REPEAT);

//	SetTextureFilter(Texture2D texture, int 过滤器);                         //设置Texture缩放过滤器模式





//	设置帧率
//	SetTargetFPS(160);									// 低帧率,四角的矩形会平滑移动效果
//	100*30全面刷新帧率60+
//	100*15全面刷新帧率
	SetTargetFPS(70);
//		设置默认绘制到mesh
	BeginTextureMode(mesh);
//	******
//		取消绘制的GPU画布

	EndTextureMode();
//		设置默认绘制到桌面
	BeginDrawing();
//		黑色覆盖全部屏幕
	ClearBackground(BLACK);
	DrawTexturePro(mesh.texture, {0, 0, 750, 750}, {0, 0, 750, 750}, {0, 0}, 0, WHITE);
//		结束绘制的桌面
	EndDrawing();

	// 绘制,粘贴自8.测试DrawTexture 与11.备份 10测试
	int drawx;
	int drawy;
	int mousex;
	int mousey;
	int drawi;
	int drawj;
	mousex = 0;
	mousey = 0;
	drawx = 0;
	drawy = 0;
	drawi = 0;
	drawj = 0;


//	拖拽
	int draftflag;
	int draftx;
	int drafty;
	int gamex;
	int gamey;
//	记录长按时,鼠标按下去的位置,减出长按拖拽距离
	int oldx;
	int oldy;
	draftflag = 0;
	draftx = 0;
	drafty = 0;
//	draftx=bkmeshwidth*pixnum/2;
//	drafty=bkmeshheight*pixnum/2;
	gamex = 0;
	gamey = 0;

//	滚轮放大缩小
	float camerasize;
	camerasize = 1.0f;

	int zoom;
	int time;
	zoom = 0;
	//记录滚轮次数,滚动快,放缩快
	int cnt = 0;


	// 测试碰撞目标
	int mousewidth = 10;
//		int mouseheight = 0;
	int mouseheight = 3;
	int targetheight = 45;
	int targetwidth = 25;
	int targeti = mapi - 10;
//	int targetj = 10;
	int targetj = 20;



	int ax;								// 加速度,解决松开就停而产生的变量,延长运动时期,和按键时期不同
	int ay;
//	ax=0;
//	ay=0;
	ax = 0;
	ay = 0;
	int speedx;										// 玩家速度
	int speedy;
	speedx = 0;
	speedy = 0;


	int playeri;									// 玩家位置
	int playerj;


	int playerx;
	int playery;

	playery = mapi * pixnum / 2;
	playerx = mapj * pixnum / 2;

//	playeri = mapi - 1;								// 左上角
//	playerj = 0;
	playeri = mapi / 2;
	playerj = mapj / 2;

	int oldplayeri;									// 恢复原状
	int oldplayerj;

	oldplayeri = playeri;
	oldplayerj = playerj;

	int cntv2;										// 原来的一个cnt被摄像机使用了
	int timev2;										// time 也被摄像机滚轮放大zoom限制使用了
	cntv2 = 0;
	timev2 = 0;


	float k = 0.0f;


//	int timev3;
//	timev3 = 0;

//	int atking;											// 记录是否直线攻击
//	atking = 0;											// 不攻击记录为0




//	这里开始主循环
	while (!WindowShouldClose()) {

//		按键后增加速度
		if (IsKeyDown(KEY_A)) {
			ax += -1;
		}
		if (IsKeyDown(KEY_D)) {
			ax += 1;
		}
		if (IsKeyDown(KEY_W)) {
			ay += 1;
		}
		if (IsKeyDown(KEY_S)) {
			ay += -1;
		}


		// 键盘松开,加速度消失
		// 四个 if 合并成两个
		if (IsKeyUp(KEY_A) && IsKeyUp(KEY_D)) {
			ax = 0;
			speedx = 0;
		}
		if (IsKeyUp(KEY_W) && IsKeyUp(KEY_S)) {
			ay = 0;
			speedy = 0;
		}

		// 加速度限制
		if (ax > 1) {
			ax = 1;
		} else if (ax < -1) {
			ax = -1;
		}
		if (ay > 1) {
			ay = 1;
		} else if (ay < -1) {
			ay = -1;
		}
		speedy += ay;
		speedx += ax;

		// 速度限制
		if (speedx > 1) {
			speedx = 1;
		} else if (speedx < -1) {
			speedx = -1;
		}

		if (speedy > 1) {
			speedy = 1;
		} else if (speedy < -1) {
			speedy = -1;
		}
		// playerj+speedx 解决复制粘贴 改名不全的导致的 playerj -speedx
		// 但是只修改网格,不是像素绘制上去,瓦片贴图是一直刷新的,

		// 禁用红色矩形移动
		// 不禁用,检测贴图移动
		if (0 < playeri + speedy && playeri + speedy < mapi && 0 < playerj + speedx && playerj + speedx < mapj) {
			playeri += speedy;											// 因为往下是减少,速度增加,速度往下是正的,变成负的是每帧的距离
			playerj += speedx;

//			map[oldplayeri][oldplayerj] = 224;
			mapv2[oldplayeri][oldplayerj] = 224;

			map[playeri][playerj] = 2024;
			oldplayeri = playeri;
			oldplayerj = playerj;

		}

		// 红色像素移动
		if (0 < playery + speedy && playery + speedy < mapi * 30 && 0 < playerx + speedx && playerx + speedx < mapj * 30) {
			playerx = playerx + speedx;
			playery = playery + speedy;
//			BeginTextureMode(mesh);
//			DrawPixel(playerx,playery,{255,0,0,255});
//			EndTextureMode();
		}

		// 如果玩家在区域里
		if (region != NULL) {
			if (playerx >= region->targetj * pixnum &&
			    playerx < (region->targetj + region->targetwidth)*pixnum &&
			    // 注意坐标系y向下数值会减小,所以是小于,等于是测试得到的,原来的BUG是移动一格任何出现轨迹
			    // +1是发现高度差一行
			    // 原来是+1到了上一格子。target是网格坐标,mapi是最顶上,所以+1是往上平移一格,因为绘制是GPU左下角绘制,所以是网格的左下角,所以需要更上一格的左下角。
			    // 是小于上一格子的左下角,大于等于最底下一格子的左下角
			    playery < (region->targeti + 1) * pixnum &&
			    // 没有发现漏打region->targethieght
			    playery >= (region->targeti + 1 - region->targetheight)*pixnum) {
				regionflag = 1;

			} else {
				int n = 0;
				for (n = 0; n < enemysum; n++) {
					if (playerx >= enemy[n].targetj * pixnum &&
					    playerx < (enemy[n].targetj + enemy[n].targetwidth)*pixnum &&
					    playery < (enemy[n].targeti + 1) * pixnum &&
					    playery >= (enemy[n].targeti + 1 - enemy[n].targetheight)*pixnum) {
						region = &enemy[n];
						break;
					}
				}
				// 全部看一遍发现没有重叠的
				if (n == enemysum) {
					regionflag = 0;
				}
			}
		}

		// 把之前绘制像素碰撞检测分离到数据处理部分
		if (regionflag == 1) {
			if (region->mapv3[-1 + (region->targetheight) * pixnum - ( playery - (region->targeti - region->targetheight + 1) * pixnum )][playerx - region->targetj * pixnum] == 0) {
				playerx -= speedx;
				playery -= speedy;
			}
		}



		// 解决缩小放大绘制时出现的绘制情况,原因是旧位置放大倍数给了新数据,现在是新放大倍数给当前数据
//		版本7,继续版本5的调参数
		if (GetMouseWheelMove() < 0) {
			zoom = -1;
			cnt++;
		} else if (GetMouseWheelMove() > 0) {
			zoom = 1;
			cnt--;
		}
//		30改10,配合0.99改0.95,增加灵敏度
//		10改5,配合0.95改0.97,增加减少放大差距,提高鼠标滚动延长效果
//		5改5,配合0.97改0.98,增加减少放大差距,提高鼠标滚动延长效果
//		5改5,配合0.98改0.981,复位1.00001,解决无法复位,回不到1问题
//		5改5,配合0.981改0.9811,复位1.00000,解决无法复位,回不到1问题
//		5改5,配合0.981改0.99,复位1.00000,解决到0.01再返回无法复位,回不到1.0问题
		// 0.99改成0.98在4.版本后

		if (cnt != 0 && time < 5) {
//			改30参数,影响放缩时间
			time++;
			if (zoom > 0) {
//				加法改乘法,放大感觉平均,没有了越小,再缩小一次,缩小明显更小的追加情况,原因是数值小了,追加固定数据,倍数影响大
				camerasize = camerasize * 0.97;
//				改0.99缩小参数,影响每次循环缩小倍数,一次缩小的突然更小程度
				if (camerasize < 0.01) {
					camerasize = 0.01;
				}
			} else if (zoom < 0) {
				camerasize = camerasize / 0.97;
				if (camerasize > 40) {
					camerasize = 40;
				}
			}
//			解决复位之后,重复写0问题
		} else if (time != 0) {
			time = 0;
//			zoom = 0;
//			多次滚轮,则延长摄像机缩放
			if (cnt < 0) {
				cnt++;
			}
			if (cnt > 0) {
				cnt--;
			}
//			消耗完累计次数,停止滚动
			if (cnt == 0) {
				zoom = 0;
			}
		}

//		注意是pressed 不是 Down
		if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) {
			draftflag = 1;
			oldx = GetMouseX();
			oldy = GetMouseY();
		}
		if (draftflag == 1) {
			mousex = GetMouseX();
			mousey = GetMouseY();
			draftx = gamex - (mousex - oldx) / camerasize;
			drafty = gamey - (mousey - oldy) / camerasize;
		}
		if (IsMouseButtonUp(MOUSE_BUTTON_RIGHT)) {
			draftflag = 0;
			oldx = 0;
			oldy = 0;
			gamex = draftx;
			gamey = drafty;
		}



		// 完成角色切换控制,缩小倍数锁定玩家,不能拖拽

		// 记录旧数据,缩小还原
		static int olddraftx;
		static int olddrafty;
		static int recoverflag = 0;							// 摄像机回到原来位置的控制信号,原来是靠camerasize if 不够用
		static int followflag = 0;							// 追随
//		olddraftx = draftx;
//		olddrafty = drafty;
		// 在确定网格左上角坐标之前覆盖玩家追随数据
		// 追加追随,在放大倍数一定后,数据覆盖屏蔽旧拖拽
		if (camerasize > 1) {
//			draftx = playerx + bkmeshwidth / 2 - showjv2 * pixnumv2 / camerasize;
//			drafty = playery + bkmeshheight / 2 - showiv2 * pixnumv2 / camerasize;
//			gamex=playerx;
//			gamey=playery;

//			DrawTexturePro(mesh.texture, {(draftx - limitleft ) + bkmeshwidth / 2 - showjv2*pixnumv2 / 2 / camerasize,
//			(drafty - limittop + bkmeshheight / 2) - showiv2*pixnumv2 / 2 / camerasize,
//			showjv2*pixnumv2 / camerasize, showiv2*pixnumv2 / camerasize},
//		{0, 0, showjv2 * pixnumv2, showiv2 * pixnumv2}, {0, 0}, 0, WHITE);

//		 采样中心 是玩家	draftx + bkmeshwidth / 2 - showjv2*pixnumv2 / 2 / camerasize = playerx

			// 根据旧的记录可知,数据draftx 是一开始的左上角区域坐标,draftx+bkmeshwidth/2是中心 ,这是延续当时开发先产生的结论,本质是一开始draftx 是0 ,但是playerx是mapi*pixnum/2
//			draftx = playerx - bkmeshwidth / 2;
//			drafty =( mapi*pixnum-playery) - bkmeshheight / 2;

			if (followflag == 0) {
				olddraftx = draftx;
				olddrafty = drafty;
				followflag = 1;
			}

			// 根据旧的记录可知,数据draftx 是一开始的左上角区域坐标,draftx+bkmeshwidth/2是中心 ,这是延续当时开发先产生的结论,本质是一开始draftx 是0 ,但是playerx是mapi*pixnum/2
			draftx = playerx - bkmeshwidth / 2;
			drafty = ( mapi * pixnum - playery) - bkmeshheight / 2;

			followflag = 1;
			recoverflag = 1;							// 记录覆盖数据已更新
		} else {
			followflag = 0;
		}

		// 第一次切换
		if (followflag == 0 && recoverflag == 1) {
			draftx = olddraftx;
			drafty = olddrafty;
			recoverflag = 0;
		}




		if (side != 0) {
			// 新增边界检测
			if (draftx < 0) {
				draftx = 0;
			} else if (draftx > maxgamex ) {										// 配合limitleft+60 可以看见边界白边
				draftx = maxgamex;
			}
//打表发现左上角出界刷新,实际比较矩形限制在很小的区域 60*60,原来的表示则是750*750大小的区域
//		0<0不会执行,不能等于,否则出界
//		if 又改wihle 解决拖拽时出现绘制点,原因是旧坐标没来得及更新
//		+1解决side=0时去除采样复位导致的抖动,避免死循环
//		但是导致偏移,鼠标尖点击不准确,于是回滚代码去除+1
			while (draftx < limitleft ) {
//			limitleft -= side * pixnum+1;											// side*pixnum 替换 pixnum 但是 limitleft 不变化
				limitleft -= side * pixnum;											// side*pixnum 替换 pixnum 但是 limitleft 不变化
			}
			while (draftx > limitleft + 2 * side * pixnum) {						//+60 改 +30 又改 +60 左上角移动两个边距就是2*30
//			limitleft += side * pixnum+1;
				limitleft += side * pixnum;
			}
//		新增边界检测
			if (drafty < 0) {
				drafty = 0;
			} else if (drafty > maxgamey) {
				drafty = maxgamey;
			}

			while (drafty < limittop ) {
//			limittop -= side * pixnum+1;
				limittop -= side * pixnum;
			}
			while (drafty > limittop + 2 * side * pixnum) {							// +60 改 +30 又改 +60,见到底部白边
//			limittop += side * pixnum+1;
				limittop += side * pixnum;
			}

			bkmeshmapj = limitleft / pixnum;												// 关键在只要保证draftx<=limitleft + 2 * side * pixnum,边界就不会出来刚好靠边,数组打印
//		bkmeshmapi = mapi - 1 -  bkmeshmapmaxi - limittop / pixnum;							// 269 -27 -0 + 27 -i = 269 -i =269 -0 =269 = 数组最后一个
			bkmeshmapi = mapi  -  bkmeshmapmaxi - limittop / pixnum;						// 270 -27 -0 + 27 -i = 270 -i =270 -1 =269 = 数组最后一个
		}

//		// 追加追随,在放大倍数一定后,数据覆盖屏蔽旧拖拽
//		if (camerasize > 0.1) {
//			draftx = playerx + bkmeshwidth / 2 - showjv2 * pixnumv2 / camerasize;
//			drafty = playery + bkmeshheight / 2 - showiv2 * pixnumv2 / camerasize;
			gamex=playerx;
			gamey=playery;
//
			DrawTexturePro(mesh.texture, {(draftx - limitleft ) + bkmeshwidth / 2 - showjv2*pixnumv2 / 2 / camerasize,
			(drafty - limittop + bkmeshheight / 2) - showiv2*pixnumv2 / 2 / camerasize,
			showjv2*pixnumv2 / camerasize, showiv2*pixnumv2 / camerasize},
		{0, 0, showjv2 * pixnumv2, showiv2 * pixnumv2}, {0, 0}, 0, WHITE);
//
//	}


//		改变顺序,计算完偏移再算绘制,解决用上一次偏移坐标组合这一处偏移绘制
		if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
//			drawx = GetMousePosition().x;
//			无中生有坐标系变化过程
//			750,实际穷举描述得到,在点一下,在鼠标坐标系是0,100,靠顶边,
//			在GPU坐标系里0,100则是靠底边100像素,
//			然后实际上是直接取反然后加上高度上限,发现原来可以
//			最后重整旧测试代码实现
//			drawy = 750 - GetMousePosition().y;
//			drawy = 751 - GetMousePosition().y;
//			if (drawx < 0 || drawx > 750 || drawy < 0 || drawy > 750)
//			发现可以直接写,标注数据变化,于是重新命名变量
			mousex = GetMousePosition().x;
			mousey = GetMousePosition().y;
//			测试之后,追加等号,发现等号设置在0处解决问题,750-0=750,750/30=25,数组出界,750-1=749,749/30=24,
//			可知减的多,不出界,剩下的少,于是就不出界
//			if (mousex < 0 || mousex > showiv2 * pixnum || mousey <= 0 || mousey > showiv2 * pixnum) {
//			side=0 时进行检测,节约性能
			if (mousex < 0 || mousex > showjv2 * pixnumv2 || mousey <= 0 || mousey > showiv2 * pixnumv2) {

			} else {
//				int positionx = 0 + draftx/ camerasize;
//				int positionx = 0 + draftx + showjv2 * pixnum / 2 - showjv2 * pixnum / 2 / camerasize;
//				解决采样中心是mesh中心后,绘制偏移也修改
//				int positionx = 0 + draftx + bkmeshwidth / 2 - showjv2 * pixnum / 2 / camerasize;
				int positionx = 0 + draftx + bkmeshwidth / 2 - showjv2 * pixnumv2 / 2 / camerasize;
//				int positiony = 0 + drafty / camerasize;
//				int positiony = 0 + drafty + showiv2 * pixnum / 2 - showiv2 * pixnum / 2 / camerasize;
//				int positiony = 0 + drafty + bkmeshheight / 2 - showiv2 * pixnum / 2 / camerasize;
				int positiony = 0 + drafty + bkmeshheight / 2 - showiv2 * pixnumv2 / 2 / camerasize;
//				相对于左下角位置,水平方向就是当前左下角距离加鼠标横着距离左边界
				drawx = mousex / camerasize + positionx;			// 乘camerasize不行,测试除法,发现也不行,换测试位置
//				回滚,测试发现x 除法可以在水平移动多少,对应绘制多少
//				竖直方向,可以理解成先算距离左下角距离,然后再加上左下角实际对应的地图点
//				缩小后,750变化,可以理解成坐标上限增加,原来坐标系变化需要750-,现在变成1500- 对应两倍坐标系变化
				drawy =  mousey / camerasize + positiony;		// 750/camerasize
//				测试750/camerasize,发现偏移随放大倍数增加,改成乘camerasize 发现刚好适配
				drawj = drawx / pixnum;
				drawi = (mapi * pixnum - drawy) / pixnum;
//				出界闪退BUG解决方案,drawj没有问题,受到边界限制 maxgamex
				// 但是由于side =0 时会禁用之前的拖拽检测,于是丢失了上面的限制,所以还是得增加 j x 方向的越界检测
				if (drawi >= mapi || drawi < 0 || drawj < 0 || drawj >= mapj) {

				} else {
//					for (int j = 0; j < 10; j++) {
//						map[drawi][drawj + j] = 1949;
//					}

					for (int i = 0; i < mouseheight; i++) {
						for (int j = 0; j < mousewidth; j++) {
							if (drawi - i > 0 && drawi - i < mapi) {
								if (drawj + j > 0 && drawj + j < mapj) {
									map[drawi - i][drawj + j] = 1949;
								} else {
									break;
								}
							} else {
								break;
							}

						}
					}

//					atking = 1;
					// 找到一个没有运行的炮弹并启动
					for (int i = 0; i < boomsum; i++) {
						// 发现没有运行
						if (booms[i].atking == 0) {
//							启动运行
							booms[i].atking = 1;
							// 开始运行时间重置为0
							booms[i].timev3 = 0;
							// 记录位置,可描述为起点,实际是记录所在直线
							booms[i].playerjv2 = playerj;
							booms[i].playeriv2 = playeri;
//							终点
							booms[i].drawiv2 = drawi;
							booms[i].drawjv2 = drawj;
							// 记录覆盖点,重置为0,避免旧数据覆盖到其他地方
							booms[i].oldx = 0;
							booms[i].oldy = 0;
							// 炮弹数目
							have--;
							break;
						}
					}

				}
			}
		}

		// 恢复旧贴图数据
		for (int n = 0; n < enemysum; n++) {
			for (int i = 0; i < enemy[n].targetheight; i++) {
				for (int j = 0; j < enemy[n].targetwidth; j++) {
//					map[enemy[n].targeti - i][enemy[n].targetj + j] = enemy[n].oldmap[i][j];
					// 追加边界检测,解决闪退问题
					if (enemy[n].targeti - i >= 0 && enemy[n].targeti - i < mapi && enemy[n].targetj + j >= 0 && enemy[n].targetj + j < mapj) {
						map[enemy[n].targeti - i][enemy[n].targetj + j] = enemy[n].oldmap[i][j];
					}
				}
			}
		}

//		lineatk(booms, boomsum, map);
//		lineatk(booms, boomsum, mapv2);
		lineatk(booms, boomsum, map);												// 敌人map重新替换mapv2 ,实现局部刷新


//		for (int n = 0; n < boomsum; n++) {
			checkboom(booms[n], enemy, map, enemysum, mapi, mapj);
//			checkboom(booms[n], enemy, mapv2, enemysum, mapi, mapj);
//		}
		checkend(booms, boomsum, &have, map, mapi, mapj);
//		checkend(booms, boomsum, &have, mapv2, mapi, mapj);



		// 敌人伏击检测
		for (int n = 0; n < enemysum; n++) {
			int bangi;
			int bangj;
			int bangwidth;
			int bangheight;

			if (bang(playeri, playerj, 10, 10, enemy[n].targeti + 50, enemy[n].targetj - 50, enemy[n].targetwidth + 50 + 50, enemy[n].targetheight + 50 + 50, &bangi, &bangj, &bangwidth, &bangheight)) {
				for (int m = 0; m < boomsumv2; m++) {
					if (boomsv2[m].atking == 0) {
						boomsv2[m].atking = 1;
						boomsv2[m].playerjv2 = enemy[n].targetj;
						boomsv2[m].playeriv2 = enemy[n].targeti;
						boomsv2[m].drawiv2 = playeri;
						boomsv2[m].drawjv2 = playerj;
						boomsv2[m].timev3 = 0;
						havev2--;
						break;
					}
				}
			}
		}

		// 敌人的炮弹移动
//		lineatk(boomsv2, 100, map);
//		lineatk(boomsv2, 100, mapv2);
		lineatk(boomsv2, 100, map);


		// 炮弹命中检测
		for (int n = 0; n < 100; n++) {
			int bangi;
			int bangj;
			int bangwidth;
			int bangheight;
			if (boomsv2[n].atking == 1) {
				if (bang(playeri, playerj, 10, 10, boomsv2[n].oldy - 10 / 2, boomsv2[n].oldx - 10 / 2, 10, 10, &bangi, &bangj, &bangwidth, &bangheight)) {
					boomsv2[n].isboom = 1;

				}
			}

		}

//		checkend(boomsv2, boomsumv2, &havev2, map, mapi, mapj);
//		checkend(boomsv2, boomsumv2, &havev2, mapv2, mapi, mapj);
		checkend(boomsv2, boomsumv2, &havev2, map, mapi, mapj);



		// 敌人移动
		for (int n = 0; n < enemysum; n++) {
			if (enemy[n].islive == 1) {
				if (enemy[n].targetj < playerj) {
					enemy[n].targetj += 1;
				} else if (enemy[n].targetj > playerj) {
					enemy[n].targetj -= 1;
				}

				if (enemy[n].targeti > playeri) {
					enemy[n].targeti -= 1;
				} else if (enemy[n].targeti < playeri) {
					enemy[n].targeti += 1;
				}
			}

		}

		// 敌人绘制,但是帧率低,没有复制粘贴过来的跑到帧率高
//		for (int n = 0; n < 100; n++) {
//			if (enemy[n].islive) {
//				for (int i = 0; i < enemy[n].targetheight; i++) {
//					for (int j = 0; j < enemy[n].targetwidth; j++) {
//						map[enemy[n].targeti - i][enemy[n].targetj + j] = 7788;
//					}
//				}
//			}
//		}

		// 重新采样数据,要在炮弹发射之后,这样不会覆盖炮弹轨迹,敌人移动之后重新采样
		for (int n = 0; n < enemysum; n++) {
			for (int i = 0; i < enemy[n].targetheight; i++) {
				for (int j = 0; j < enemy[n].targetwidth; j++) {
//					enemy[n].oldmap[i][j] = map[enemy[n].targeti - i][enemy[n].targetj + j];
					// 追加边界检测,解决闪退问题
					if (enemy[n].targeti - i >= 0 && enemy[n].targeti - i < mapi && enemy[n].targetj + j >= 0 && enemy[n].targetj + j < mapj) {
						enemy[n].oldmap[i][j] = map[enemy[n].targeti - i][enemy[n].targetj + j];
					}
				}
			}
		}

		// 绘制敌人
		for (int n = 0; n < enemysum; n++) {
			for (int i = 0; i < enemy[n].targetheight; i++) {
				for (int j = 0; j < enemy[n].targetwidth; j++) {
					// 发现是没有越界检测所以导致100 个时,碰到边界闪退
					if (enemy[n].targeti - i < 0 || enemy[n].targeti - i >= mapi || enemy[n].targetj + j < 0 || enemy[n].targetj + j >= mapj) {
						break;
					} else {
//						map[enemy[n].targeti - i][enemy[n].targetj + j] = 1;
//						mapv2[enemy[n].targeti - i][enemy[n].targetj + j] = 1;
						// 之前覆盖,原来是重新绘制时,有的颜色所在网格序号相同,导致不会重绘,留下贴图
						// 已经使用另一个序号覆盖,和之前的map 序号不同,总是会重新绘制
						map[enemy[n].targeti - i][enemy[n].targetj + j] = 2024;
					}

				}
			}
		}


		// 敌人复活检测
		// 发现每次复活都会有残留贴图,原来是复活后先贴图,玩家再移动,于是没有覆盖第一次贴图,可知复活在贴图之后
//		enemylive = 0;
//		for (int n = 0; n < enemysum; n++) {
//			if (enemy[n].islive == 1) {
//				enemylive++;
//			}
//		}
//
//
//		if (enemylive < 5) {
//			for (int n = 0; n < 5; n++) {
//				if (enemy[n].islive == 0) {
//					enemy[n].islive = 1;
//					enemy[n].targeti = GetRandomValue(0, mapi - 1);
//					enemy[n].targetj = GetRandomValue(0, mapj - 1);
//					enemy[n].targetwidth = GetRandomValue(10, 20);
//					enemy[n].targetheight = GetRandomValue(10, 20);
//					enemylive++;
//
//					// 敌人复活,对应贴图重新设置大小
//					enemy[n].picture.texture.width = enemy[n].targetwidth * pixnum;
//					enemy[n].picture.texture.height = enemy[n].targetheight * pixnum;
//				}
//			}
//		}



		for (int n = 0; n < boomsum; n++) {
			// 只检测正在运行的炮弹
			if (booms[n].atking == 1) {
				checkboom(booms[n], enemy, map, enemysum, mapi, mapj);
			}

//			checkboom(booms[n], enemy, mapv2, enemysum, mapi, mapj);
		}
//		checkend(booms, boomsum, &have, map, mapi, mapj);
//		checkend(booms, boomsum, &have, mapv2, mapi, mapj);
		checkend(booms, boomsum, &have, map, mapi, mapj);									// 重新启用map,敌人重绘贴图替换mapv2



		//碰撞加局部显示
		// 两两排列组合-四宫格 左边端点在区间里,左边端点不在区间里,右边端点在区间里,右边端点不在区间里
		static int bangi = 0;
		static int bangj = 0;
		static int bangwidth = 40;
		static int bangheight = 30;

		int isbang = bang(drawi, drawj, mousewidth, mouseheight, targeti, targetj, targetwidth, targetheight, &bangi, &bangj, &bangwidth, &bangheight);

		if (isbang) {
			for (int i = 0; i > bangheight; i--) {
				for (int j = 0; j < bangwidth; j++) {
					map[bangi + i][bangj + j] = 2024;
				}
			}
		}

		// 把玩家绘制到敌人贴图里面
		if (regionflag == 1) {
			BeginTextureMode(region->picture);
			// 高度-距离左下角位置,因为playex是往下时数值增加,减去的多,则越靠近GPU画布的左下角
			// ,+1是一格网格,测试出现的。-1是像素偏移
//			DrawPixel(playerx - region->targetj * pixnum, -1+(region->targetheight) * pixnum - ( playery - (region->targeti - region->targetheight+1) * pixnum ), {255, 0, 0, 255});

//			DrawPixel(playerx - region->targetj * pixnum, -1 + (region->targetheight) * pixnum - ( playery - (region->targeti - region->targetheight + 1) * pixnum ), {255, 0, 0, 255});
			// 增加区域碰撞,如果遇到,就恢复原状,模拟像素碰撞
//			if (region->mapv3[-1 + (region->targetheight) * pixnum - ( playery - (region->targeti - region->targetheight + 1) * pixnum )][playerx - region->targetj * pixnum] == 0) {
//				playerx -= speedx;
//				playery -= speedy;
//			} else {
//				DrawPixel(playerx - region->targetj * pixnum, -1 + (region->targetheight) * pixnum - ( playery - (region->targeti - region->targetheight + 1) * pixnum ), {255, 0, 0, 255});
//			}
			DrawPixel(playerx - region->targetj * pixnum, -1 + (region->targetheight) * pixnum - ( playery - (region->targeti - region->targetheight + 1) * pixnum ), {255, 0, 0, 255});


			EndTextureMode();
		}

//		设置默认绘制到mesh
		BeginTextureMode(mesh);

//		DrawPixel(playerx, playery, {255, 0, 0, 255});

//		改成了1,并且最后是等于号因为等于时,对应数组0,0格子,其实是绘制时发现对不上号和更新总是偏下
		for (int i = 1; i <= bkmeshmapmaxi; i++) {
			if (bkmeshmapmaxi - i + bkmeshmapi < 0) {
				break;
			}
			for (int j = 0; j < bkmeshmapmaxj; j++) {
				if (j + bkmeshmapj > mapj) {						// 如果出界就取消绘制
					break;
				}
				// 增加side 是0 为单宫格检测,才进行比较检测,选择刷新小片网格
				if (side == 0 && meshmap[bkmeshmapmaxi  - i ][j] == map[bkmeshmapmaxi - i + bkmeshmapi][j + bkmeshmapj]) {

				} else {
					meshmap[bkmeshmapmaxi  - i ][j] = map[bkmeshmapmaxi - i + bkmeshmapi][j + bkmeshmapj];
					// 绘制矩形,原点(0,0)在左下角,现在是从左下角一行一行往上绘制
					if (map[bkmeshmapmaxi - i + bkmeshmapi][j + bkmeshmapj] == 9999) {
//						DrawRectangle(j * pixnum, bkmeshmapmaxi * pixnum - i * pixnum - pixnum, pixnum, pixnum, { 255,  255, 255, 255});
						DrawRectangle(j * pixnum, bkmeshmapmaxi * pixnum - i * pixnum, pixnum, pixnum, { 255,  255, 255, 255});
//						DrawRectangle(j * pixnum, bkmeshmapmaxi*pixnum-i * pixnum, pixnum, pixnum, {255, 0, 0, 255});
					} else if (map[bkmeshmapmaxi - i + bkmeshmapi][j + bkmeshmapj] == 2024) {
						DrawRectangle(j * 30, bkmeshheight - i  * 30, pixnum, pixnum, {255, 0, 0, 255});

					} else if (map[bkmeshmapmaxi - i + bkmeshmapi][j + bkmeshmapj] == 224) {
						DrawRectangle(j * 30, bkmeshheight - i  * 30, pixnum, pixnum, {125, 125, 0, 255});

					} else if (map[bkmeshmapmaxi - i + bkmeshmapi][j + bkmeshmapj] == 1224) {
						DrawRectangle(j * 30, bkmeshheight - i  * 30, pixnum, pixnum, {0, 255, 0, 255});

					} else if (map[bkmeshmapmaxi - i + bkmeshmapi][j + bkmeshmapj] == 1949) {
						DrawRectangle(j * pixnum, bkmeshheight  - i * pixnum, pixnum, pixnum, {0, 0, 0, 255});
					} else if (map[bkmeshmapmaxi - i + bkmeshmapi][bkmeshmapj + j] == 7788) {
						DrawRectangle(j * pixnum, bkmeshheight - i * pixnum, pixnum, pixnum, {255, 255, 255, 255});
					} else {
//					60是边界,-30是i=0时,要760打印就没有空间了,730打印30高正方形,刚好是760,同时对应底部的黑边消失了,这就是整体下移动30像素
//						DrawRectangle(j * 30, 750 + 60 - i * 30 - 30, 30, 30, {map[bkmeshmapmaxi - i + bkmeshmapi][j + bkmeshmapj] * 1 % 255, map[bkmeshmapmaxi - i + bkmeshmapi][j + bkmeshmapj] * 21 % 255, 255, 255});
						// 替换常数
//						DrawRectangle(j * pixnum, bkmeshmapmaxi * pixnum - i * pixnum -pixnum, pixnum, pixnum, {map[bkmeshmapmaxi - i + bkmeshmapi][j + bkmeshmapj] * 1 % 255, map[bkmeshmapmaxi - i + bkmeshmapi][j + bkmeshmapj] * 21 % 255, 255, 255});
						DrawRectangle(j * pixnum, bkmeshmapmaxi * pixnum - i * pixnum, pixnum, pixnum, {map[bkmeshmapmaxi - i + bkmeshmapi][j + bkmeshmapj] * 1 % 255, map[bkmeshmapmaxi - i + bkmeshmapi][j + bkmeshmapj] * 21 % 255, 255, 255});
					}
//				左下角
					DrawRectangle(0, 0, 150, 150, {154, 154, 154, 255});
//				左上角
					DrawRectangle(0, bkmeshmapmaxi * pixnum - 100,  30, 100, {255, 255, 255, 255});
//				屏幕右上角对应的白色矩形
					DrawRectangle(bkmeshmapmaxi * pixnum - pixnum, bkmeshmapmaxi * pixnum - 100,  30, 100, {255, 255, 255, 255});
//				屏幕右下角对应的红色矩形
					DrawRectangle(bkmeshmapmaxi * pixnum - pixnum, 0,  pixnum, 100, {255, 0, 0, 255});
//				绘制坐标系是左下角0,0)y正方向向上
				}

			}
		}

// 颜色复位
		// 新增复位在绘制后
//		for (int i = 0; i < mapi; i++) {
//			for (int j = 0; j < mapj; j++) {
//				map[i][j] = mapv2[i][j];
//			}
//		}

		// 绘制敌人贴图,不再是网格
		for (int n = 0; n < enemysum; n++) {
			DrawTexture(enemy[n].picture.texture, enemy[n].targetj * pixnum, (enemy[n].targeti - enemy[n].targetheight + 1)*pixnum, WHITE);
		}
		// 绘制像素玩家
//		DrawPixel(playerx, playery, {255, 0, 0, 255});
		if (regionflag == 0) {
			DrawPixel(playerx, playery, {255, 0, 0, 255});
		}



//		取消绘制的GPU画布
		EndTextureMode();

		// 敌人复活
		enemylive = 0;
		for (int n = 0; n < enemysum; n++) {
			if (enemy[n].islive == 1) {
				enemylive++;
			}
		}


		if (enemylive < 5) {
			for (int n = 0; n < 5; n++) {
				if (enemy[n].islive == 0) {
					enemy[n].islive = 1;
					enemy[n].targeti = GetRandomValue(0, mapi - 1);
					enemy[n].targetj = GetRandomValue(0, mapj - 1);
					enemy[n].targetwidth = GetRandomValue(10, 20);
					enemy[n].targetheight = GetRandomValue(10, 20);
					enemylive++;

					// 敌人复活,对应贴图重新设置大小
					enemy[n].picture.texture.width = enemy[n].targetwidth * pixnum;
					enemy[n].picture.texture.height = enemy[n].targetheight * pixnum;


					// 重新采样地图数据
					for (int i = 0; i < enemy[n].targetheight; i++) {
						for (int j = 0; j < enemy[n].targetwidth; j++) {
//							enemy[n].oldmap[i][j] = map[enemy[n].targeti - i][enemy[n].targetj + j];
							// 追加边界检测,解决闪退问题
							if (enemy[n].targeti - i >= 0 && enemy[n].targeti - i < mapi && enemy[n].targetj + j >= 0 && enemy[n].targetj + j < mapj) {
								enemy[n].oldmap[i][j] = map[enemy[n].targeti - i][enemy[n].targetj + j];
							}
						}
					}


					// 复活,重新设置数组,在追加mapv3,仿照采样地图数据,初始化,打印,复位
					for (int y = 0; y < enemy[n].targetheight; y++) {
						for (int x = 0; x < enemy[n].targetwidth; x++) {
							enemy[n].mapv3[x][y] = (x + y) % 255;
						}
					}
				}
			}
		}


//		设置默认绘制到桌面
		BeginDrawing();
//		黑色覆盖全部屏幕
		ClearBackground(BLACK);
//		采样坐标系是左上角0,0,y轴正方向向下
//		重新理解:由于在不改这行代码的情况下,改其他地方的代码,跑通了。实现了效果,再次理解数据变化:draftx>60时,draftx-limitleft<60,实现在网格缓冲区采样
//		可通过边界白边左上角和右上角左右拖拽可得实际采样位置在缓冲区左右
//		DrawTexturePro(mesh.texture, {draftx - limitleft, drafty - limittop, 750 / camerasize, 750 / camerasize}, {0, 0, 750, 750}, {0, 0}, 0, WHITE);
//		DrawTexturePro(mesh.texture, {draftx - limitleft, drafty - limittop, showj*pixnum / camerasize, showi*pixnum / camerasize}, {0, 0, showjv2 * pixnum, showiv2 * pixnum}, {0, 0}, 0, WHITE);
//		DrawTexturePro(mesh.texture, {draftx - limitleft, drafty - limittop, showj*pixnum / camerasize+700, showi*pixnum / camerasize+700}, {0, 0, showjv2 * pixnum, showiv2 * pixnum}, {0, 0}, 0, WHITE);
// 关于draftx y 和之前的正面没有区别,其实是因为坐标系y轴变化,但是可以变成同一个坐标系,就是一个人倒着看地图,头朝地脚朝天,代码中保留旧形式,只有数组的坐标参考是从最大开始打印的
//		DrawTexturePro(mesh.texture, {draftx - limitleft, drafty - limittop, showj*pixnum / camerasize, showi*pixnum / camerasize}, {0, 0, showjv2 * pixnum, showiv2 * pixnum}, {0, 0}, 0, WHITE);
//		DrawTexturePro(mesh.texture, {draftx - limitleft, drafty - limittop, showj*pixnum / camerasize, showi*pixnum / camerasize}, {0, 0, showjv2 * pixnum, showiv2 * pixnum}, {0, 0}, 0, WHITE);
//		DrawTexturePro(mesh.texture, {(-draftx+750/2)-750/2/camerasize, (-drafty+750/2)-750/2/camerasize, 750 / camerasize, 750 / camerasize}, {0, 0, 750, 750}, {0, 0}, 0, WHITE);
//		DrawTexturePro(mesh.texture, {(draftx- limitleft +showjv2*pixnum/2)-showjv2*pixnum/2/camerasize, drafty - limittop, showj*pixnum / camerasize, showi*pixnum / camerasize}, {0, 0, showjv2 * pixnum, showiv2 * pixnum}, {0, 0}, 0, WHITE);
//		DrawTexturePro(mesh.texture, {(draftx - limitleft + showjv2*pixnum / 2) - showjv2*pixnum / 2 / camerasize, (drafty - limittop + showiv2 * pixnum / 2) - showiv2*pixnum / 2 / camerasize, showj*pixnum / camerasize, showi*pixnum / camerasize}, {0, 0, showjv2 * pixnum, showiv2 * pixnum}, {0, 0}, 0, WHITE);
//		DrawTexturePro(mesh.texture, {(draftx - limitleft + showjv2*pixnum / 2) - showjv2*pixnum / 2 / camerasize, (drafty - limittop + showiv2 * pixnum / 2) - showiv2*pixnum / 2 / camerasize, showjv2*pixnum / camerasize, showiv2*pixnum / camerasize}, {0, 0, showjv2 * pixnum, showiv2 * pixnum}, {0, 0}, 0, WHITE);
//	解决bug 绘制出来是把左上角粘贴到中间,实际改完,增加距离,原来是采样采样多了,中心是mesh的中心所以要加上meshwidth/2
//		DrawTexturePro(mesh.texture, {(draftx - limitleft )+ bkmeshwidth / 2 - showjv2*pixnum / 2 / camerasize, (drafty - limittop + bkmeshheight / 2) - showiv2*pixnum / 2 / camerasize, showjv2*pixnum / camerasize, showiv2*pixnum / camerasize}, {0, 0, showjv2 * pixnum, showiv2 * pixnum}, {0, 0}, 0, WHITE);
		DrawTexturePro(mesh.texture, {(draftx - limitleft ) + bkmeshwidth / 2 - showjv2*pixnumv2 / 2 / camerasize, (drafty - limittop + bkmeshheight / 2) - showiv2*pixnumv2 / 2 / camerasize, showjv2*pixnumv2 / camerasize, showiv2*pixnumv2 / camerasize}, {0, 0, showjv2 * pixnumv2, showiv2 * pixnumv2}, {0, 0}, 0, WHITE);

		DrawText(TextFormat("mouseV1 %.0f,%.0f", GetMousePosition().x, GetMousePosition().y), 35, 12, 30, BLUE);
		DrawText(TextFormat("mouseV2 %.0f,%.0f", GetMousePosition().x, 750 - GetMousePosition().y), 35, 62, 30, BLUE);

		DrawText(TextFormat("draftxyV2 %d,%d", draftx, drafty), 35, 152, 30, RED);
		DrawText(TextFormat("camerasize %f", camerasize), 35, 192, 30, BLACK);
		DrawText(TextFormat("limitleft,right %d %d", limitleft, limitleft + 60), 35, 222, 30, BLACK);
		DrawText(TextFormat("limittop,bottom %d %d", limittop, limittop + 60 ), 35, 252, 30, BLACK);
		DrawText(TextFormat("%i FPS", GetFPS()), 300, 2 + 10, 40, WHITE);
		DrawText(TextFormat("maxside j %d", bkmeshmapj + bkmeshmapmaxj ), 340, 20 + 60, 40, WHITE);
		DrawText(TextFormat("maxside i %d", bkmeshmapi + bkmeshmapmaxi ), 340, 20 + 100, 40, WHITE);

		DrawText(TextFormat("drawjiV2 %d,%d", drawj, drawi), 35, 92, 30, RED);
		DrawText(TextFormat("drawxyV2 %d,%d", drawx, drawy), 35, 122, 30, RED);
		DrawText(TextFormat("playerijV2 %d,%d", playeri, playerj), 665, 12, 40, RED);
		DrawText(TextFormat("playerspeed %d,%d", speedx, speedy), 665, 62, 40, RED);
		DrawText(TextFormat("playeraxy %d,%d", ax, ay), 665, 102, 40, RED);
		DrawText(TextFormat("k %f", k), 695, 192, 40, RED);
		DrawText(TextFormat("have boom %d", have), 1195, 12, 40, RED);

		DrawText(TextFormat("have boomv2 %d", havev2), 1195, 62, 40, RED);
		DrawText(TextFormat("playerx y %d %d", playerx, playery), 1195, 102, 40, RED);
		DrawText(TextFormat("regonflag %d", regionflag), 1195, 162, 40, RED);

//		DrawText(TextFormat("have boom %d %d %d %d", bangi, bangj, bangwidth, bangheight), 1195, 62, 40, RED);
		// 如果碰撞了才打印,否则不打印,来模拟检测是否撞上了
		if (isbang) {
			DrawText(TextFormat("have boom %d %d %d %d", bangi, bangj, bangwidth, bangheight), 1195, 62, 40, RED);
		}
//		结束绘制的桌面
		EndDrawing();
	}
// 卸载GPU画布,释放GPU内存
	UnloadRenderTexture(mesh);
// 关闭后台的其他GPU 数据
	CloseWindow();
	return 0;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2067651.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络编程知识点总结

物理链路网络运输会话表示应用 物链网运会表应 实际的数据帧 TCP和UDP的异同&#xff08;笔试面试&#xff09; 主机&#xff1a;host 转换&#xff1a;to 网络&#xff1a;network uint32_t htonl(uint32_t hostlong); //将4字节无符号整数的主机字节序转换为网络字节序&a…

云计算实训32——roles基本用法、使用剧本安装nginx、使用roles实现lnmp

一、安装nginx并更改其端口 编辑hosts配置文件 [rootmo ~]# vim /etc/ansible/hosts 创建目录 [rootmo ~]# mkdir /etc/ansible/playbook 编辑配置文件 [rootmo ~]# vim /etc/ansible/playbook/nginx.yml 执行测试 [rootmo ~]# ansible-playbook /etc/ansible/playbook/n…

菜鸟的进击之.net6控制台应用程序接收参数

1、新建控制台应用程序&#xff0c;新建-添加项目-控制台应用 2、3、下一步&#xff0c;填写项目名称和代码存放的位置 3、下一步&#xff0c;框架选择.net 6 &#xff0c;点击创建 4、然后项目就创建完成啦&#xff0c; 5、在可以直接在Program.cs写方法一些简单的逻辑&#x…

Rustrover、IDEA 的 Rust 类型不显示(已解决)

关键词&#xff1a;rustrover 类型不显示&#xff0c;rustrover 不显示类型&#xff0c;IntelliJ IDEA Rust 类型不显示&#xff0c;IntelliJ IDEA Rust 不显示类型 若移动端访问不佳&#xff0c;请使用 –> Github版 背景 博主手欠&#xff0c;使用 IntelliJ IDEA 时&am…

四款流行英文翻译工具,助你轻松应对翻译难题

作为一名教培行业的工作人员&#xff0c;我经常需要处理大量的英文文件&#xff0c;从教材到学术论文&#xff0c;再到各种国际交流的资料。翻译工具成了我工作中不可或缺的帮手。今天&#xff0c;我就来跟大家聊聊我用过的几款翻译工具在翻译英文文件时的表现如何呢&#xff1…

超越IP-Adapter!阿里提出UniPortrait,可通过文本定制生成高保真的单人或多人图像。

阿里提出UniPortrait&#xff0c;能根据用户提供的文本描述&#xff0c;快速生成既忠实于原图又能灵活调整的个性化人像&#xff0c;用户甚至可以通过简单的句子来描述多个不同的人物&#xff0c;而不需要一一指定每个人的位置。这种设计大大简化了用户的操作&#xff0c;提升了…

手机游玩植物大战僵尸杂交版V2.3.7最新版教程(文章末尾免费直接下载链接)

手机游玩植物大战僵尸杂交版V2.3.7最新版教程 【V2.3.7全面升级】植物大战僵尸杂交版&#xff1a;跨平台终极安装指南 - 苹果、安卓、电脑、电视兼容&#xff0c;界面革新&#xff0c;16卡槽扩展&#xff0c;高分辨率支持&#xff0c;BUG修复&#xff0c;畅享游戏乐趣 前言 …

市盈率的概念

写篇有关市盈率的【不务正业】的内容。 重要公式 市盈率 官方的定义 平均市盈率&#xff1d;∑(收盘价发行数量)/∑(每股收益发行数量)&#xff0c;统计时剔除亏损及暂停上市的上市公司。 静态市盈率 滚动市盈率&#xff08;TTM&#xff09; 股票市盈率的意义 如果某股票有较…

探索数据结构:图(二)之图的遍历,Kruskal与Prim算法

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;数据结构与算法 贝蒂的主页&#xff1a;Betty’s blog 1. 图的遍历 图的遍历方式一般分为两种&#xff1a;深度优先遍历与广度…

gurobi中引入松弛变量和剩余变量的用法

文章目录 1. 松弛变量&#xff1a;用于“≤”不等式约束数学表达式 2. 剩余变量&#xff1a;用于“≥”不等式约束数学表达式 3. 目标函数中的松弛变量数学表达式 4. Gurobi中的实现对于“≤”不等式的松弛变量&#xff1a;对于“≥”不等式的剩余变量&#xff1a; 5. 总结 在G…

p2p、分布式,区块链笔记: IPFS库Helia的文件系统Unix File System (UnixFS)

Unix File System (UnixFS) Helia中定义一个UnixFS类用于文件处理。The Unix File System (UnixFS) is the data format used to represent files and all their links and metadata in IPFS.。UnixFS中的方法封装了常见的文件系统操作&#xff0c;使得在去中心化文件系统中处…

跨越时代的Zynq PL编程:从xdevcfg到FPGA Manager的进化

引言 在嵌入式系统设计与开发的广阔领域中&#xff0c;Xilinx Zynq平台以其独特的ARM处理器与FPGA可编程逻辑&#xff08;PL&#xff09;的结合&#xff0c;成为了众多创新项目的首选。然而&#xff0c;随着技术的不断进步&#xff0c;Zynq PL的编程方式也经历了从经典到现代的…

【UCB CS61C】Lecture 2 3 - C Basics

目录 C 语言的编译&#xff08;Compilation&#xff09;变量类型&#xff08;Variable Types&#xff09;字符&#xff08;Characters&#xff09; C 语言的类型转换&#xff08;Typecasting&#xff09;类型函数&#xff08;Typed Functions&#xff09; 结构体&#xff08;St…

【C++ Primer Plus习题】3.6

问题: 解答: #include <iostream> using namespace std;int main() {float miles 0;float gallons 0;float gallon 0;cout << "请输入驱车里程(单位为英里):";cin >> miles;cout << "请输入使用的汽油量(单位为加仑):";cin &g…

【数据结构】一篇讲清楚什么是堆? 带图食用超详细~

目录 一、堆的概念 1.堆是一个完全二叉树 2.堆分为大根堆和小根堆。 3.堆与优先级队列的关系 二、堆操作 1.向下调整 2.删除堆顶元素 3.添加新元素 4.构建堆 A&#xff1a;自底向上构建 B&#xff1a;自顶向下构建 C&#xff1a;两种方式对比 三、尝试自己编程实现堆…

redis实战——go-redis的使用与redis基础数据类型的使用场景(二)

一.go-redis操作hash 常用命令&#xff1a; redisClient.HSet("map", "name", "jack") // 批量设置 redisClient.HMSet("map", map[string]interface{}{"a": "b", "c": "d", "e"…

基于springmvc实现文件上传

1.导入jar包 2.修改配置类 在springmvc.xml添加bean <!-- 配置文件上传处理器 --><bean id"multipartResolver" class"org.springframework.web.multipart.commons.CommonsMultipartResolver"><!-- 设置在内存中允许的最大文件大小&#x…

趣味算法------柠檬水摊

目录 题目概述&#xff1a; 解题思路&#xff1a; 具体代码&#xff1a; 总结&#xff1a; 题目概述&#xff1a; 在柠檬水摊上&#xff0c;每个柠檬水售价 5 元。客户正在排队向您购买&#xff0c;并且一次订购一份柠檬水。 每位顾客只会购买一份柠檬水&#xff0c;并支付 5…

【python】火灾检测图像处理方法设计(源码+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

深入探讨Java多线程

我的主页&#xff1a;2的n次方_ 1. 多线程的概念 多线程是指在同一个程序中同时执行多个线程的技术。线程是操作系统能够独立调度和执行的最小单位。在Java中&#xff0c;线程由Thread类来表示&#xff0c;所有的线程都是通过这个类或其子类来创建和控制的。通过合理的多线…