public void Lower(int pos) { if (this._Values.Count == 0) { return; } int num = pos; int num2 = pos * 2 + 1; int num3 = pos * 2 + 2; while (true) { int num4 = num; num2 = num * 2 + 1; num3 = num * 2 + 2; if (num2 < this._Values.Count && HValue.Compare(this._Values[num2], this._Values[num4])) { num4 = num2; } if (num3 < this._Values.Count && HValue.Compare(this._Values[num3], this._Values[num4])) { num4 = num3; } if (num4 == num) { break; } HValue value = this._Values[num]; this._Values[num] = this._Values[num4]; this._Values[num4] = value; num = num4; } }
/// <summary> /// 什么算法,我很懵逼啊????????????? /// </summary> /// <param name="p"></param> /// <param name="c"></param> /// <returns></returns> private int GetDirection(HValue p, HValue c) { int num = (int)(c.X - p.X); int num2 = (int)(c.Y - p.Y); return((num + 1) * 3 + num2); }
public void Push(HValue value) { this._Values.Add(value); int pos = this._Values.Count - 1; this.Upper(pos); this.PushCount++; }
/// <summary> /// 比较评估 /// </summary> /// <param name="left"></param> /// <param name="right"></param> /// <returns></returns> public static bool Compare(HValue left, HValue right) { if (Math.Abs(right.Key - left.Key) < 0.1f) //key值相等 ,比较cost { return(Math.Abs(right.Cost - left.Cost) >= 0.1f && left.Cost > right.Cost); } return(left.Key < right.Key); }
public HValue Pop() { if (this._Values.Count >= 1) { HValue result = this._Values[0]; this._Values[0] = this._Values[this._Values.Count - 1]; this._Values.RemoveAt(this._Values.Count - 1); this.Lower(0); return(result); } return(new HValue()); }
public int Find(HValue instance) { if (this._Values != null) { for (int i = 0; i < this._Values.Count; i++) { if (instance.X == this._Values[i].X && instance.Y == this._Values[i].Y) { return(i); } } } return(-1); }
public void Upper(int pos) { int num = pos; int num2 = (pos - 1) / 2; while (true) { num2 = (num - 1) / 2; if (num == 0 || !HValue.Compare(this._Values[num], this._Values[num2])) { break; } HValue value = this._Values[num]; this._Values[num] = this._Values[num2]; this._Values[num2] = value; num = num2; } }
/// <summary> /// 获取分配给指定网格坐标的缓存索引 /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> private HValue getHValue(int x, int y) { if (this.path[x, y] == -1) { if (this.cacheIndex == this.cacheCount) //缓存索引达到最大缓存数量,最大缓存数加1000 { for (int i = 0; i < 1000; i++) { HValue hValue = new HValue(); hValue.Reset(); this.HValueCache.Add(hValue); } this.cacheCount += 1000; } this.path[x, y] = this.cacheIndex; this.cacheIndex++; } return(this.HValueCache[this.path[x, y]]); }
public bool Validate() { bool flag = true; for (int i = 0; i < this._Values.Count; i++) { if (i * 2 + 1 < this._Values.Count && HValue.Compare(this._Values[2 * i + 1], this._Values[i])) { flag = false; } if (i * 2 + 2 < this._Values.Count && HValue.Compare(this._Values[2 * i + 2], this._Values[i])) { flag = false; } if (!flag || i * 2 >= this._Values.Count) { break; } } return(flag); }
private void RequestPathsImmed(Vector3 startPoint, Vector3 endPoint, int collisionSize, int maxComputeCount = 8000) { while (!this.heap[0].IsEmpty || !this.heap[1].IsEmpty) { int num; if (this.heap[0].Count < this.heap[1].Count) { num = 0; } else { num = 1; } if (this.heap[0].Count == 0) { num = 1; } if (this.heap[1].Count == 0) { num = 0; } HValue hValue = this.heap[num].Pop(); hValue.Mark = (short)(num * this.markBase + 2); for (int i = 0; i < 8; i++) { float num2 = (float)(this.dx[i] * this.dx[i] + this.dy[i] * this.dy[i]); num2 = (float)Math.Sqrt((double)num2); int num3 = (int)hValue.X + this.dx[i]; int num4 = (int)hValue.Y + this.dy[i]; bool flag = this.IsValidForWalk((int)hValue.X, (int)hValue.Y, collisionSize); if (Math.Abs(num2 - 1f) < 0.01f) { flag = this.IsValidForWalk(num3, num4, collisionSize); } else { for (int j = 0; j <= 1; j++) { for (int k = 0; k <= 1; k++) { flag = (flag && this.IsValidForWalk((int)hValue.X + j * this.dx[i], (int)hValue.Y + k * this.dy[i], collisionSize)); } } } if (flag) { this.curPathValue = this.getHValue(num3, num4); if (this.curPathValue.Mark == -1) { float num5 = hValue.Cost + num2; float num6 = this.HeapHFunction(num3, num4, this.heapX[1 - num], this.heapY[1 - num]); this.curPathValue.Set((short)num3, (short)num4, num5, num5 + num6); this.curPathValue.PreX = hValue.X; this.curPathValue.PreY = hValue.Y; this.curPathValue.Mark = (short)(num * this.markBase + 1); this.heap[num].Push(this.curPathValue); } if ((int)this.curPathValue.Mark == num * this.markBase + 1) { float num7 = hValue.Cost + num2; if (num7 + 0.1f < this.curPathValue.Cost) { float num8 = this.Distance((int)hValue.X, (int)hValue.Y, num3, num4); int pos = this.heap[num].Find(this.curPathValue); this.curPathValue.Set((short)num3, (short)num4, num7, num7 + num8); this.curPathValue.PreX = hValue.X; this.curPathValue.PreY = hValue.Y; this.heap[num].Upper(pos); } } this.computeTick++; if (this.computeTick > maxComputeCount && i == 7) { this.computeTick = 0; return; } if (num == 0) { float num9 = this.Distance((int)this.nearestTarget.X, (int)this.nearestTarget.Y, this.heapX[1], this.heapY[1]); float num10 = this.Distance(num3, num4, this.heapX[1], this.heapY[1]); if (num10 < num9) { this.nearestTarget = this.curPathValue; } float num11 = this.nearestTarget.Cost + 8f * num9; float num12 = hValue.Cost + num10; if (num12 > num11 && this.heap[0].PushCount > 4096 && this.heap[1].IsEmpty) { hValue = this.nearestTarget; this.pathHValues.Add(hValue); while (hValue.PreX != -1 && hValue.PreY != -1) { this.pathHValues.Add(this.getHValue((int)hValue.PreX, (int)hValue.PreY)); hValue = this.getHValue((int)hValue.PreX, (int)hValue.PreY); } for (int l = 0; l < this.pathHValues.Count / 2; l++) { HValue value = this.pathHValues[l]; this.pathHValues[l] = this.pathHValues[this.pathHValues.Count - l - 1]; this.pathHValues[this.pathHValues.Count - l - 1] = value; } Vector3 end = new Vector3((float)((int)this.nearestTarget.X - this.halfWidth) * this.gridSize, 0f, (float)((int)this.nearestTarget.Y - this.halfHeight) * this.gridSize); this.paths = this.BuildPath(this.pathHValues, startPoint, end, collisionSize); this.pathFindEnd = true; if (this.pathFindEndBack != null) { this.pathFindEndBack(this.paths); } return; } } if (this.curPathValue.Mark >= 0 && (int)(this.curPathValue.Mark / 10) != num) { HValue[] array = new HValue[2]; array[num] = hValue; array[1 - num] = this.curPathValue; this.paths.Clear(); hValue = array[0]; this.pathHValues.Add(hValue); while (hValue.PreX != -1 && hValue.PreY != -1) { this.pathHValues.Add(this.getHValue((int)hValue.PreX, (int)hValue.PreY)); hValue = this.getHValue((int)hValue.PreX, (int)hValue.PreY); } for (int l = 0; l < this.pathHValues.Count / 2; l++) { HValue value2 = this.pathHValues[l]; this.pathHValues[l] = this.pathHValues[this.pathHValues.Count - l - 1]; this.pathHValues[this.pathHValues.Count - l - 1] = value2; } hValue = array[1]; this.pathHValues.Add(hValue); while (hValue.PreX != -1 && hValue.PreY != -1) { this.pathHValues.Add(this.getHValue((int)hValue.PreX, (int)hValue.PreY)); hValue = this.getHValue((int)hValue.PreX, (int)hValue.PreY); } this.paths = this.BuildPath(this.pathHValues, startPoint, endPoint, collisionSize); this.pathFindEnd = true; if (this.pathFindEndBack != null) { this.pathFindEndBack(this.paths); } return; } } } } }
/// <summary> /// 请求获取指定条件的路径 /// </summary> /// <param name="startPoint">起点</param> /// <param name="endPoint">终点</param> /// <param name="collisionSize">(移动体)碰撞尺寸</param> /// <param name="pathFindEndBack">路径搜索结束事件回调</param> /// <param name="maxComputeCount">最大的搜索计算次数计数上限</param> public void RequestPaths(Vector3 startPoint, Vector3 endPoint, int collisionSize, MapPath.PathFindEndBack pathFindEndBack = null, int maxComputeCount = 8000) { try { this.pfStartPoint = startPoint; this.pfEndPoint = endPoint; this.pfCollisionSize = collisionSize; this.pathFindEnd = false; this.pathFindResult = true; this.pathFindEndBack = pathFindEndBack; this.paths.Clear(); this.computeTick = 0; this.heapX = new int[2]; this.heapY = new int[2]; //起点网格坐标 this.heapX[0] = Mathf.FloorToInt(startPoint.x / this.gridSize) + this.halfWidth; this.heapY[0] = Mathf.FloorToInt(startPoint.z / this.gridSize) + this.halfHeight; //终点网格坐标 this.heapX[1] = Mathf.FloorToInt(endPoint.x / this.gridSize) + this.halfWidth; this.heapY[1] = Mathf.FloorToInt(endPoint.z / this.gridSize) + this.halfHeight; if (this.heapX[0] == this.heapX[1] && this.heapY[0] == this.heapY[1]) //原地,直接完成 { this.paths.Add(endPoint); this.pathFindEnd = true; if (pathFindEndBack != null) { pathFindEndBack(this.paths); } } else { //初始化heap列表 for (int i = 0; i < 2; i++) { if (this.heap[i] == null) { this.heap[i] = new Heap(); } this.heap[i].Clear(); } //重置HValeCache for (int i = 0; i < this.HValueCache.Count; i++) { this.HValueCache[i].Reset(); } //path列表重置 for (int i = 0; i < this.width; i++) { for (int j = 0; j < this.height; j++) { this.path[i, j] = -1; } } this.cacheIndex = 0; for (int k = 0; k < 2; k++) { int num = this.heapX[k]; int num2 = this.heapY[k]; for (int i = -1; i <= 1; i++) //将起点和终点的9宫格信息加入heap表 { for (int j = -1; j <= 1; j++) { int num3 = num + i; int num4 = num2 + j; Vector3 vector = new Vector3((float)(this.heapX[0] - this.halfWidth) * this.gridSize, 0f, (float)(this.heapY[0] - this.halfHeight) * this.gridSize); Vector3 vector2 = new Vector3((float)(this.heapX[1] - this.halfWidth) * this.gridSize, 0f, (float)(this.heapY[1] - this.halfHeight) * this.gridSize); Vector3 vector3 = (k != 0) ? vector2 : vector; Vector3 vector4 = new Vector3((float)(num3 - this.halfWidth) * this.gridSize, 0f, (float)(num4 - this.halfHeight) * this.gridSize); vector3.y = (vector4.y = 0f); float num5 = Vector3.Distance(vector3, vector4); float num6 = this.TryWalkDistance(vector3, vector4, collisionSize); if (Math.Abs(num6 - num5) < 0.01f) { HValue hValue = this.getHValue(num3, num4); hValue.Set((short)num3, (short)num4, num5, 0f); hValue.Mark = (short)(1 + k * this.markBase); hValue.PreX = -1; hValue.PreY = -1; this.heap[k].Push(hValue); } } } } this.nearestTarget = this.heap[0].Peek(); int num7 = 8; this.dx = new int[num7]; this.dy = new int[num7]; for (int i = 0; i < num7; i++) { float num8 = (float)i * 2f * 3.14159274f / (float)num7; this.dx[i] = this.Sign(Math.Cos((double)num8)); this.dy[i] = this.Sign(Math.Sin((double)num8)); } this.pathHValues.Clear(); this.RequestPathsImmed(this.pfStartPoint, this.pfEndPoint, this.pfCollisionSize, maxComputeCount); } } catch (Exception ex) //路径搜索失败 { this.paths = new List <Vector3>(); if (GameScene.isEditor) { LogSystem.Log(new object[] { string.Concat(new object[] { "寻路失败: 起始点 ", startPoint, " 目标点 : ", endPoint, " 错误消息 : ", ex.Message }) }); } } }