using RichCreator.Utility.Structs; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using RichCreator.Utility.Skills; using RichCreator.Utility.InputControl; using RichCreator.Utility.PathFinding; using RichCreator.Utility.Utilitys; namespace RichCreator.Utility.Maps { /// /// 房间信息 /// public class HouseInfo { public HouseInfo(HousePathInfo houseInfo) { this.HousePathInfo = houseInfo; InitPathInfo(null); } public HouseInfo(Int32 index,MapType mapType,bool isEnd, HIDCode[] skills,Int32[] withoutNumber,Int32 fromHouseIndex) { this.Index = index; this.MapType = mapType; this.IsEnd = isEnd; this.FromHouseIndex = fromHouseIndex; Skills = new SkillQueue(); for (int i = 0; skills!=null&&i < skills.Length; i++) { Skills.EnQueue(false,skills[i]); } if (index < 0) { throw new ArgumentOutOfRangeException("houseIndex"); } try { this.HousePathInfo = HousePathInfo.From(this.MapType, index); } catch (Exception e) { throw e; } InitPathInfo(withoutNumber); } /// /// 房间编号 /// public Int32 Index { get; set; } /// /// 来自房间索引 /// public Int32 FromHouseIndex { get; set; } private Direction[] doorDirection = null; /// /// 门的位置 /// todo:cacel /// public Direction[] DoorDirection { get { return doorDirection; } } /// /// 技能队列 /// public SkillQueue Skills { get; set; } /// /// 是否为结束房间 /// public bool IsEnd { get; set; } /// /// 地图类型 /// public MapType MapType { get; set; } /// /// 房间信息 /// public HousePathInfo HousePathInfo { get; private set; } /// /// 路径查找器 /// private Dijkstra PathFinder { get; set; } /// /// 定位字典 /// private Dictionary LocationDic = new Dictionary(); /// /// 排除数字 /// public Dictionary WithoutNumber = new Dictionary(); /// /// 屏幕坐标转地图坐标 /// /// /// /// /// public ZTPoint ScreenToMapCoordinate(ZTPoint screenCoordinate,ParametersPoint locationCoor) { if (!LocationDic.ContainsKey(locationCoor.Parameter)) { throw new ArgumentOutOfRangeException("不存在的定位点,parameter:" + locationCoor.Parameter.ToString()); } //目标屏幕坐标+(定位点地图坐标-定位点屏幕坐标) return screenCoordinate.Add(LocationDic[locationCoor.Parameter].Sub(locationCoor.Point)); } /// /// 地图坐标转屏幕坐标 /// /// /// /// /// public ZTPoint MapToScreenCoordinate(ZTPoint mapCoordinate, ParametersPoint locationCoor) { if (!LocationDic.ContainsKey(locationCoor.Parameter)) { throw new ArgumentOutOfRangeException("不存在的定位点,parameter:" + locationCoor.Parameter.ToString()); } //目标地图坐标-(定位点地图坐标-定位点屏幕坐标) return mapCoordinate.Sub(LocationDic[locationCoor.Parameter].Sub(locationCoor.Point)); } /// /// 两点之间寻路 /// /// /// public List FindPath(ZTPoint start, ZTPoint end) { if (start.Equals(end)) { return new List(); } //查询两点间是否连通 if (Iscross(start, end)) { //两点直接连通 return new List() { end }; } //确保两点不在障碍物里 ZTPoint startPathGuid = ZTPoint.Empty; ZTPoint endPathGuid = ZTPoint.Empty; bool inObstacle = EnsureNotInObstacle(out startPathGuid, start); inObstacle = EnsureNotInObstacle(out endPathGuid, end) || inObstacle; //查询两点间是否连通 if (inObstacle && Iscross(startPathGuid, endPathGuid)) { //两点直接连通 List points = new List(); if (!start.Equals(startPathGuid)) { points.Add(startPathGuid); } if (!end.Equals(endPathGuid)) { points.Add(endPathGuid); } points.Add(end); return points; } //把两点添加到寻路网中 AddConnectivityEdgeToFinder(startPathGuid, endPathGuid); //寻路,组合路径 List paths = this.PathFinder.ShortestPath(startPathGuid, endPathGuid); //去除寻路网中 RemoveStartAndEndVerticeFromFinder(endPathGuid, endPathGuid); //生成的路径不包含第一个点,拟如果第一个点是路径引导,则加入路径 if (!start.Equals(startPathGuid)) { paths.Insert(0, startPathGuid); } //如果最后一个点是路径引导点,测加上终点 if (!end.Equals(endPathGuid)) { paths.Add(end); } return paths; } /// /// 是否在下一关进门点区域内 /// /// /// /// public bool IsInNextGatePoint(out ParametersPoint nextGatePoint, ZTPoint rolePosition) { nextGatePoint = ParametersPoint.Empty; const Int32 X_OFFSET = 5; const Int32 Y_OFFSET = 5; for (Int32 i = 0; i < this.HousePathInfo.NextGates.Count; i++) { ParametersPoint nextGate = this.HousePathInfo.NextGates[i]; if (GeoHelper.IsInRect(rolePosition, new ZTRectangle(nextGate.Point.X- X_OFFSET, nextGate.Point.Y- Y_OFFSET, nextGate.Point.X+ X_OFFSET, nextGate.Point.Y+ Y_OFFSET))) { nextGatePoint = nextGate; return true; } } return false; } /// /// 获取指定方向的进门点 /// /// /// public ZTPoint GetNextGatePoint(Direction dir) { int dirNumber = 0; switch (dir) { case Direction.Up: dirNumber = 0; break; case Direction.Right: dirNumber = 1; break; case Direction.Bottom: dirNumber = 2; break; case Direction.Left: dirNumber = 3; break; } for (int i = 0; i < this.HousePathInfo.NextGates.Count; i++) { if (dirNumber == this.HousePathInfo.NextGates[i].Parameter) { return this.HousePathInfo.NextGates[i].Point; } } throw new ArgumentOutOfRangeException("house index:" + this.Index.ToString() + ",direction :" + dir.ToString() + " is not exists!~"); } /// /// 判断两点间是否连通 /// /// /// /// private bool Iscross(ZTPoint start, ZTPoint end) { for (int i = 0; i < this.HousePathInfo.Obstacles.Count; i++) { Intersection interSection = GeoHelper.IntersectionOf(new ZTLinePoint(start, end), this.HousePathInfo.Obstacles[i]); if (interSection != Intersection.None) { return false; } } return true; } /// /// 是否在障碍物里,如果在障碍物里则返回最近的不在障碍物点 /// /// /// true:在障碍物,false:不在障碍物里 private bool EnsureNotInObstacle(out ZTPoint pathGuidePoint,ZTPoint source) { pathGuidePoint = ZTPoint.Empty; //点是否在障碍物里 ZTPolygon obstacle = ZTPolygon.Empty; for (int i = 0; i < this.HousePathInfo.Obstacles.Count; i++) { ZTPolygon temp = this.HousePathInfo.Obstacles[i]; if (GeoHelper.IntersectionOf(source, temp) != Intersection.None) { obstacle = this.HousePathInfo.Obstacles[i]; break; } } if (obstacle.Equals(ZTPolygon.Empty)) { //不在障碍物内 pathGuidePoint = source; return false; } //点是否在路径导引区域 for (int i = 0; i < this.HousePathInfo.PathGuides.Count; i++) { ZTTargetPolygon temp = this.HousePathInfo.PathGuides[i]; if (GeoHelper.IntersectionOf(source, temp.Polygon) != Intersection.None) { pathGuidePoint = temp.Target; return true; } } //计算距离障碍物外最近的距离 double distance = 0; ZTPoint lastPoint = ZTPoint.Empty; for (int i = 0; i < obstacle.Points.Length; i++) { if (i == 0) { lastPoint = obstacle.Points[i]; distance = GeoHelper.GetPointDistance(lastPoint, pathGuidePoint); } double lastDistance = GeoHelper.GetNearestDistance(new ZTLinePoint(lastPoint, obstacle[i]), pathGuidePoint); if (lastDistance < distance) { distance = lastDistance; } if (distance <= 0) { distance = 0; break; } } //查找最近离开障碍物的点 ZTPoint testPoint = ZTPoint.Empty; Int32 maxDistance = Math.Max(Math.Max(source.X, this.HousePathInfo.Width - source.X), Math.Max(source.Y, this.HousePathInfo.Height - source.Y)); for (int i = (Int32)distance; i < maxDistance; i++) { //下 if (source.Y + i <= this.HousePathInfo.Height) { testPoint = new ZTPoint(source.X, source.Y + i); if (GeoHelper.IntersectionOf(testPoint, obstacle) == Intersection.None) { testPoint.Y += 10; pathGuidePoint = testPoint; break; } } //右 if (source.X <= this.HousePathInfo.Width) { testPoint = new ZTPoint(source.X + i, source.Y); if (GeoHelper.IntersectionOf(testPoint, obstacle) == Intersection.None) { testPoint.X += 10; pathGuidePoint = testPoint; break; } } //左 if (source.X - i >= 0) { testPoint = new ZTPoint(source.X - i, source.Y); if (GeoHelper.IntersectionOf(testPoint, obstacle) == Intersection.None) { testPoint.X -= 10; pathGuidePoint = testPoint; break; } } //上 if (source.Y - i >= 0) { testPoint = new ZTPoint(source.X, source.Y - i); if (GeoHelper.IntersectionOf(testPoint, obstacle) == Intersection.None) { testPoint.Y -= 10; pathGuidePoint = testPoint; break; } } } return true; } /// /// 初始化寻路器 /// private void InitPathInfo(Int32[] withoutNumber) { this.PathFinder = new Dijkstra(); //添加寻路路径 ZTLinePoint line; for (int i = 0; i < this.HousePathInfo.FindPathLines.Count; i++) { line = this.HousePathInfo.FindPathLines[i]; this.PathFinder.AddEdge(line.P1, line.P2, line.GetDistance()); } //定位点添加到字典 for (int i = 0; i < this.HousePathInfo.LocationPoints.Count; i++) { ParametersPoint pp = this.HousePathInfo.LocationPoints[i]; if (!this.LocationDic.ContainsKey(pp.Parameter)) { this.LocationDic.Add(pp.Parameter, pp.Point); } } //计算门朝向 doorDirection = new Direction[this.HousePathInfo.NextGates.Count]; for (Int32 i = 0; i < this.HousePathInfo.NextGates.Count; i++) { switch (this.HousePathInfo.NextGates[i].Parameter) { case 0: doorDirection[i] = Direction.Up; break; case 1: doorDirection[i] = Direction.Right; break; case 2: doorDirection[i] = Direction.Bottom; break; case 3: doorDirection[i] = Direction.Left; break; } } if (withoutNumber != null) { for (int i = 0; i < withoutNumber.Length; i++) { if (!this.WithoutNumber.ContainsKey(withoutNumber[i])) { this.WithoutNumber.Add(withoutNumber[i], true); } } } } /// /// 向查找器中添加起点和终点可连通的边 /// /// /// private void AddConnectivityEdgeToFinder(ZTPoint start, ZTPoint end) { Int32 distance = 0; ZTPoint point; for (int i = 0; i < this.HousePathInfo.FindPathPoints.Count; i++) { point = this.HousePathInfo.FindPathPoints[i]; if (Iscross(start, point)) { distance = (Int32)GeoHelper.GetPointDistance(start, point); this.PathFinder.AddEdge(start, point, distance); } if (Iscross(end, point)) { distance = (Int32)GeoHelper.GetPointDistance(end, point); this.PathFinder.AddEdge(end, point, distance); } } } /// /// 从查找器中移除起点和终点 /// /// /// private void RemoveStartAndEndVerticeFromFinder(ZTPoint start, ZTPoint end) { this.PathFinder.RemoveEdge(start); this.PathFinder.RemoveEdge(end); } } }