RTSManhattan.SpaceDiv.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using CommonAI.RTS;
  5. using CommonLang.Vector;
  6. using CommonLang;
  7. using CommonLang.Concurrent;
  8. using CommonAI.ZoneServer.JSGModule;
  9. using static CommonAI.ZoneServer.JSGModule.MSpaceNodeCache;
  10. namespace CommonAI.RTS.Manhattan
  11. {
  12. partial class AstarManhattan
  13. {
  14. //----------------------------------------------------------------------------------------------------------------------------
  15. /// <summary>
  16. /// 十字链表,预先寻路
  17. /// </summary>
  18. public class MSpaceAStar : RTSAstar<MSpaceAStar.MSpaceNode>
  19. {
  20. private readonly MSpaceMap smap;
  21. private readonly int div_size;
  22. private readonly AstarManhattan manhattan;
  23. private DirtyNodes<MSpaceNode> dirty_space_nodes = new DirtyNodes<MSpaceNode>();
  24. public MSpaceMap SpaceMap
  25. {
  26. get { return smap; }
  27. }
  28. internal MSpaceAStar(int uniqueID, AstarManhattan astar, int div_size)
  29. {
  30. this.manhattan = astar;
  31. this.div_size = div_size;
  32. this.smap = new MSpaceMap(uniqueID, astar, div_size);
  33. base.Init(smap);
  34. this.manhattan.terrain_map.ForEachNodes((mn) =>
  35. {
  36. mn.OnResetValue = onNodeValueReset;
  37. });
  38. }
  39. protected override void Disposing()
  40. {
  41. base.Disposing();
  42. dirty_space_nodes.Clear();
  43. }
  44. public MSpaceNode getSpaceNode(int cx, int cy)
  45. {
  46. return smap.getSpaceNode(cx, cy);
  47. }
  48. public MSpaceNode getSpaceNodeByBlock(int bx, int by)
  49. {
  50. int cx, cy;
  51. smap.Space.ToSpaceBlock(bx, by, out cx, out cy);
  52. return smap.getSpaceNode(cx, cy);
  53. }
  54. public override WayPoint GenWayPoint(MapNode node)
  55. {
  56. var wp = (node as MSpaceNode).WayPoint;
  57. wp.LinkNext(null);
  58. return wp;
  59. }
  60. //------------------------------------------------------------------------
  61. /// <summary>
  62. /// 当地表数据改变
  63. /// </summary>
  64. /// <param name="node"></param>
  65. private void onNodeValueReset(MMapNode node)
  66. {
  67. var mn = getSpaceNodeByBlock(node.BX, node.BY);
  68. if (mn != null)
  69. {
  70. dirty_space_nodes.AddDirty(mn);
  71. }
  72. }
  73. internal void beginFindPath()
  74. {
  75. if (dirty_space_nodes.Count > 0)
  76. {
  77. using (var list = ListObjectPool<MSpaceNode>.AllocAutoRelease(dirty_space_nodes.Values))
  78. {
  79. var near_table = GetNearTables(manhattan.IsInclined);
  80. foreach (var dn in list)
  81. {
  82. foreach (var offset in near_table)
  83. {
  84. var sn = getSpaceNode(dn.CX + offset[0], dn.CY + offset[1]);
  85. if (sn != null)
  86. {
  87. dirty_space_nodes.AddDirty(sn);
  88. }
  89. }
  90. }
  91. }
  92. using (var list = ListObjectPool<MSpaceNode>.AllocAutoRelease(dirty_space_nodes.Values))
  93. {
  94. foreach (var mn in list)
  95. {
  96. mn.ResetCenterAnchor();
  97. }
  98. foreach (var mn in list)
  99. {
  100. mn.ResetNext();
  101. }
  102. }
  103. dirty_space_nodes.Clear();
  104. }
  105. }
  106. //------------------------------------------------------------------------
  107. public class MSpaceMap : ITerrain<MSpaceNode>
  108. {
  109. internal readonly AstarManhattan manhattan;
  110. internal readonly SpaceDivision space;
  111. public readonly float space_full_cell_w;
  112. public readonly float space_full_cell_h;
  113. private int nodes_count;
  114. private MSpaceNodeItem nodes_matrix = new MSpaceNodeItem();
  115. public SpaceDivision Space
  116. {
  117. get { return space; }
  118. }
  119. public int TotalNodeCount
  120. {
  121. get { return nodes_count; }
  122. }
  123. internal MSpaceMap(int uniqueID, AstarManhattan mmap, int divSize)
  124. {
  125. this.manhattan = mmap;
  126. this.space = new SpaceDivision(
  127. mmap.manhattan_map.XCount,
  128. mmap.manhattan_map.YCount,
  129. divSize,
  130. divSize);
  131. this.space_full_cell_w = space.SpaceCellW * manhattan.cellw;
  132. this.space_full_cell_h = space.SpaceCellH * manhattan.cellh;
  133. this.nodes_count = space.SpaceXCount * space.SpaceYCount;
  134. nodes_matrix.data = new MSpaceNode[space.SpaceXCount, space.SpaceYCount];
  135. for (int cx = 0; cx < space.SpaceXCount; cx++)
  136. {
  137. for (int cy = 0; cy < space.SpaceYCount; cy++)
  138. {
  139. nodes_matrix.data[cx, cy] = new MSpaceNode(this, space.GetSpaceCellNodeByBlock(cx, cy));
  140. }
  141. }
  142. for (int cx = 0; cx < space.SpaceXCount; cx++)
  143. {
  144. for (int cy = 0; cy < space.SpaceYCount; cy++)
  145. {
  146. nodes_matrix.data[cx, cy].ResetNext();
  147. }
  148. }
  149. }
  150. public MSpaceNode getSpaceNode(int cx, int cy)
  151. {
  152. if (cx < space.SpaceXCount && cx >= 0 && cy < space.SpaceYCount && cy >= 0)
  153. {
  154. return nodes_matrix.data[cx, cy];
  155. }
  156. return null;
  157. }
  158. public void ForEachNodes(Action<MSpaceNode> action)
  159. {
  160. for (int cx = 0; cx < space.SpaceXCount; cx++)
  161. {
  162. for (int cy = 0; cy < space.SpaceYCount; cy++)
  163. {
  164. action(nodes_matrix.data[cx, cy]);
  165. }
  166. }
  167. }
  168. public void Dispose()
  169. {
  170. this.space.Dispose();
  171. }
  172. }
  173. public class MSpaceNode : MapNode
  174. {
  175. class NextInfo
  176. {
  177. public readonly float distance;
  178. public readonly MWayPoint path;
  179. public NextInfo(MWayPoint path)
  180. {
  181. this.path = path;
  182. this.distance = path.GetTotalDistance();
  183. }
  184. }
  185. //private readonly AstarManhattan manhattan;
  186. //private readonly SpaceDivision space;
  187. private readonly MSpaceMap map;
  188. private readonly SpaceDivision.SpaceCellNode space_node;
  189. private readonly HashMap<MapNode, NextInfo> next_links = new HashMap<MapNode, NextInfo>();
  190. private readonly MSpaceWayPoint way_point;
  191. private MMapNode center_anchor;
  192. private MSpaceNode[] nexts;
  193. /// <summary>
  194. /// 没有阻挡
  195. /// </summary>
  196. private bool no_blocks;
  197. /// <summary>
  198. /// 没有空地
  199. /// </summary>
  200. private bool no_cross;
  201. /// <summary>
  202. /// 复杂度,阻挡块越多,越复杂
  203. /// </summary>
  204. private float complexity;
  205. public int CX { get { return space_node.BX; } }
  206. public int CY { get { return space_node.BY; } }
  207. public override MapNode[] Nexts { get { return nexts; } }
  208. public MSpaceNode[] NextsSpaceNode { get { return nexts; } }
  209. public MMapNode AnchorNode { get { return center_anchor; } }
  210. internal MSpaceWayPoint WayPoint { get { return way_point; } }
  211. internal MSpaceNode(MSpaceMap map, SpaceDivision.SpaceCellNode space_node)
  212. {
  213. this.space_node = space_node;
  214. this.map = map;
  215. this.way_point = new MSpaceWayPoint(this);
  216. this.ResetCenterAnchor();
  217. }
  218. internal void ResetCenterAnchor()
  219. {
  220. int sx = (int)(space_node.BX * map.space.SpaceCellW);
  221. int sy = (int)(space_node.BY * map.space.SpaceCellH);
  222. int sw = (int)(map.space.SpaceCellW);
  223. int sh = (int)(map.space.SpaceCellH);
  224. // 检测没有空地 //
  225. this.no_cross = map.manhattan.CheckNearExpectByBlock(sx, sy, sw, sh, true);
  226. if (no_cross)
  227. {
  228. this.center_anchor = null;
  229. this.no_blocks = false;
  230. this.complexity = 0;
  231. }
  232. else
  233. {
  234. this.center_anchor = map.manhattan.FindNearMoveableNodeByBlock(sx, sy, sw, sh);
  235. //检测没有阻挡//
  236. this.no_blocks = map.manhattan.CheckNearExpectByBlock(sx, sy, sw, sh, false);
  237. //检测阻挡块数量//
  238. int bc = map.manhattan.GetNearExpectCountByBlock(sx, sy, sw, sh, true);
  239. this.complexity = map.manhattan.cell_sqrt * bc;
  240. }
  241. this.next_links.Clear();
  242. }
  243. internal void ResetNext()
  244. {
  245. if (this.center_anchor != null)
  246. {
  247. var near_table = GetNearTables(map.manhattan.IsInclined);
  248. foreach (var offset in near_table)
  249. {
  250. var next = map.getSpaceNode(CX + offset[0], CY + offset[1]);
  251. if (next != null && next.center_anchor != null)
  252. {
  253. if (this.center_anchor.AreaValue != next.center_anchor.AreaValue)
  254. {
  255. //两块区域不同(存在洞)//
  256. continue;
  257. }
  258. else if (this.no_blocks && next.no_blocks)
  259. {
  260. //两块都没有阻挡块,则不需要寻路//
  261. MWayPoint path = new MWayPoint(center_anchor);
  262. path.LinkNext(new MWayPoint(next.center_anchor));
  263. next_links.Put(next, new NextInfo(path));
  264. }
  265. else if (!map.manhattan.TouchMapLine(
  266. this.center_anchor.PosX,
  267. this.center_anchor.PosY,
  268. next.center_anchor.PosX,
  269. next.center_anchor.PosY))
  270. {
  271. //两块直接连线通过,则不需要寻路//
  272. MWayPoint path = new MWayPoint(center_anchor);
  273. path.LinkNext(new MWayPoint(next.center_anchor));
  274. next_links.Put(next, new NextInfo(path));
  275. }
  276. else
  277. {
  278. //两块之间寻路//
  279. MWayPoint path = map.manhattan.findPathInternal(this.center_anchor, next.center_anchor);
  280. if (path != null)
  281. {
  282. NextInfo info = new NextInfo(path);
  283. if (info.distance <= (map.space_full_cell_w + map.space_full_cell_h))
  284. {
  285. next_links.Put(next, info);
  286. }
  287. }
  288. }
  289. }
  290. }
  291. }
  292. this.nexts = new MSpaceNode[next_links.Count];
  293. this.next_links.Keys.CopyTo(nexts, 0);
  294. }
  295. internal void Clone(MSpaceNode data)
  296. {
  297. this.next_links.PutAll(data.next_links);
  298. this.nexts = new MSpaceNode[this.next_links.Count];
  299. this.next_links.Keys.CopyTo(this.nexts, 0);
  300. }
  301. public MWayPoint GetNextLink(MSpaceNode next)
  302. {
  303. var ret = next_links.Get(next);
  304. if (ret != null)
  305. {
  306. return ret.path;
  307. }
  308. return null;
  309. }
  310. public override bool TestCross(MapNode other)
  311. {
  312. return next_links.ContainsKey(other);
  313. }
  314. public override void Dispose()
  315. {
  316. next_links.Clear();
  317. nexts = null;
  318. }
  319. public override float GetG(MapNode target)
  320. {
  321. var t = (MSpaceNode)target;
  322. var ret = this.next_links.Get(t);
  323. if (ret != null)
  324. {
  325. return ret.distance + this.complexity;
  326. }
  327. else
  328. {
  329. float ndx = (t.AnchorNode.BX - this.AnchorNode.BX) * map.manhattan.cellw;
  330. float ndy = (t.AnchorNode.BY - this.AnchorNode.BY) * map.manhattan.cellh;
  331. return (float)Math.Sqrt((ndx * ndx) + (ndy * ndy)) + this.complexity;
  332. }
  333. }
  334. public override float GetH(MapNode father)
  335. {
  336. if (this == father)
  337. {
  338. return 0;
  339. }
  340. else
  341. {
  342. var t = (MSpaceNode)father;
  343. var ret = this.next_links.Get(t);
  344. if (ret != null)
  345. {
  346. return ret.distance + t.complexity;
  347. }
  348. else
  349. {
  350. return 0;
  351. }
  352. }
  353. }
  354. }
  355. public class MSpaceWayPoint : WayPoint
  356. {
  357. public MSpaceNode SpaceNode
  358. {
  359. get { return base.node as MSpaceNode; }
  360. }
  361. public MSpaceWayPoint Next
  362. {
  363. get { return base.next as MSpaceWayPoint; }
  364. }
  365. public MSpaceWayPoint Tail
  366. {
  367. get { return base.tail as MSpaceWayPoint; }
  368. }
  369. internal MSpaceWayPoint(MapNode map_node)
  370. : base(map_node)
  371. {
  372. }
  373. public override WayPoint Clone()
  374. {
  375. var ret = new MSpaceWayPoint(this.node);
  376. if (this.next != null)
  377. {
  378. ret.LinkNext(this.next.Clone());
  379. }
  380. return ret;
  381. }
  382. public AstarManhattan.MWayPoint ToLinkWayPoint()
  383. {
  384. if (next != null)
  385. {
  386. var ret = SpaceNode.GetNextLink(next.node as MSpaceNode);
  387. if (ret != null)
  388. {
  389. ret = ret.Clone() as AstarManhattan.MWayPoint;
  390. ret.Tail.LinkNext(this.Next.ToLinkWayPoint());
  391. return ret;
  392. }
  393. }
  394. return null;
  395. }
  396. }
  397. }
  398. }
  399. }