123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423 |
- using System;
- using System.Collections.Generic;
- using System.Text;
- using CommonAI.RTS;
- using CommonLang.Vector;
- using CommonLang;
- using CommonLang.Concurrent;
- using CommonAI.ZoneServer.JSGModule;
- using static CommonAI.ZoneServer.JSGModule.MSpaceNodeCache;
- namespace CommonAI.RTS.Manhattan
- {
- partial class AstarManhattan
- {
- //----------------------------------------------------------------------------------------------------------------------------
- /// <summary>
- /// 十字链表,预先寻路
- /// </summary>
- public class MSpaceAStar : RTSAstar<MSpaceAStar.MSpaceNode>
- {
- private readonly MSpaceMap smap;
- private readonly int div_size;
- private readonly AstarManhattan manhattan;
- private DirtyNodes<MSpaceNode> dirty_space_nodes = new DirtyNodes<MSpaceNode>();
- public MSpaceMap SpaceMap
- {
- get { return smap; }
- }
- internal MSpaceAStar(int uniqueID, AstarManhattan astar, int div_size)
- {
- this.manhattan = astar;
- this.div_size = div_size;
- this.smap = new MSpaceMap(uniqueID, astar, div_size);
- base.Init(smap);
- this.manhattan.terrain_map.ForEachNodes((mn) =>
- {
- mn.OnResetValue = onNodeValueReset;
- });
- }
- protected override void Disposing()
- {
- base.Disposing();
- dirty_space_nodes.Clear();
- }
- public MSpaceNode getSpaceNode(int cx, int cy)
- {
- return smap.getSpaceNode(cx, cy);
- }
- public MSpaceNode getSpaceNodeByBlock(int bx, int by)
- {
- int cx, cy;
- smap.Space.ToSpaceBlock(bx, by, out cx, out cy);
- return smap.getSpaceNode(cx, cy);
- }
- public override WayPoint GenWayPoint(MapNode node)
- {
- var wp = (node as MSpaceNode).WayPoint;
- wp.LinkNext(null);
- return wp;
- }
- //------------------------------------------------------------------------
- /// <summary>
- /// 当地表数据改变
- /// </summary>
- /// <param name="node"></param>
- private void onNodeValueReset(MMapNode node)
- {
- var mn = getSpaceNodeByBlock(node.BX, node.BY);
- if (mn != null)
- {
- dirty_space_nodes.AddDirty(mn);
- }
- }
- internal void beginFindPath()
- {
- if (dirty_space_nodes.Count > 0)
- {
- using (var list = ListObjectPool<MSpaceNode>.AllocAutoRelease(dirty_space_nodes.Values))
- {
- var near_table = GetNearTables(manhattan.IsInclined);
- foreach (var dn in list)
- {
- foreach (var offset in near_table)
- {
- var sn = getSpaceNode(dn.CX + offset[0], dn.CY + offset[1]);
- if (sn != null)
- {
- dirty_space_nodes.AddDirty(sn);
- }
- }
- }
- }
- using (var list = ListObjectPool<MSpaceNode>.AllocAutoRelease(dirty_space_nodes.Values))
- {
- foreach (var mn in list)
- {
- mn.ResetCenterAnchor();
- }
- foreach (var mn in list)
- {
- mn.ResetNext();
- }
- }
- dirty_space_nodes.Clear();
- }
- }
- //------------------------------------------------------------------------
- public class MSpaceMap : ITerrain<MSpaceNode>
- {
- internal readonly AstarManhattan manhattan;
- internal readonly SpaceDivision space;
- public readonly float space_full_cell_w;
- public readonly float space_full_cell_h;
- private int nodes_count;
- private MSpaceNodeItem nodes_matrix = new MSpaceNodeItem();
- public SpaceDivision Space
- {
- get { return space; }
- }
- public int TotalNodeCount
- {
- get { return nodes_count; }
- }
- internal MSpaceMap(int uniqueID, AstarManhattan mmap, int divSize)
- {
- this.manhattan = mmap;
- this.space = new SpaceDivision(
- mmap.manhattan_map.XCount,
- mmap.manhattan_map.YCount,
- divSize,
- divSize);
- this.space_full_cell_w = space.SpaceCellW * manhattan.cellw;
- this.space_full_cell_h = space.SpaceCellH * manhattan.cellh;
- this.nodes_count = space.SpaceXCount * space.SpaceYCount;
- nodes_matrix.data = new MSpaceNode[space.SpaceXCount, space.SpaceYCount];
- for (int cx = 0; cx < space.SpaceXCount; cx++)
- {
- for (int cy = 0; cy < space.SpaceYCount; cy++)
- {
- nodes_matrix.data[cx, cy] = new MSpaceNode(this, space.GetSpaceCellNodeByBlock(cx, cy));
- }
- }
- for (int cx = 0; cx < space.SpaceXCount; cx++)
- {
- for (int cy = 0; cy < space.SpaceYCount; cy++)
- {
- nodes_matrix.data[cx, cy].ResetNext();
- }
- }
- }
- public MSpaceNode getSpaceNode(int cx, int cy)
- {
- if (cx < space.SpaceXCount && cx >= 0 && cy < space.SpaceYCount && cy >= 0)
- {
- return nodes_matrix.data[cx, cy];
- }
- return null;
- }
- public void ForEachNodes(Action<MSpaceNode> action)
- {
- for (int cx = 0; cx < space.SpaceXCount; cx++)
- {
- for (int cy = 0; cy < space.SpaceYCount; cy++)
- {
- action(nodes_matrix.data[cx, cy]);
- }
- }
- }
- public void Dispose()
- {
- this.space.Dispose();
- }
- }
- public class MSpaceNode : MapNode
- {
- class NextInfo
- {
- public readonly float distance;
- public readonly MWayPoint path;
- public NextInfo(MWayPoint path)
- {
- this.path = path;
- this.distance = path.GetTotalDistance();
- }
- }
- //private readonly AstarManhattan manhattan;
- //private readonly SpaceDivision space;
- private readonly MSpaceMap map;
- private readonly SpaceDivision.SpaceCellNode space_node;
- private readonly HashMap<MapNode, NextInfo> next_links = new HashMap<MapNode, NextInfo>();
- private readonly MSpaceWayPoint way_point;
- private MMapNode center_anchor;
- private MSpaceNode[] nexts;
- /// <summary>
- /// 没有阻挡
- /// </summary>
- private bool no_blocks;
- /// <summary>
- /// 没有空地
- /// </summary>
- private bool no_cross;
- /// <summary>
- /// 复杂度,阻挡块越多,越复杂
- /// </summary>
- private float complexity;
- public int CX { get { return space_node.BX; } }
- public int CY { get { return space_node.BY; } }
- public override MapNode[] Nexts { get { return nexts; } }
- public MSpaceNode[] NextsSpaceNode { get { return nexts; } }
- public MMapNode AnchorNode { get { return center_anchor; } }
- internal MSpaceWayPoint WayPoint { get { return way_point; } }
- internal MSpaceNode(MSpaceMap map, SpaceDivision.SpaceCellNode space_node)
- {
- this.space_node = space_node;
- this.map = map;
- this.way_point = new MSpaceWayPoint(this);
- this.ResetCenterAnchor();
- }
- internal void ResetCenterAnchor()
- {
- int sx = (int)(space_node.BX * map.space.SpaceCellW);
- int sy = (int)(space_node.BY * map.space.SpaceCellH);
- int sw = (int)(map.space.SpaceCellW);
- int sh = (int)(map.space.SpaceCellH);
- // 检测没有空地 //
- this.no_cross = map.manhattan.CheckNearExpectByBlock(sx, sy, sw, sh, true);
- if (no_cross)
- {
- this.center_anchor = null;
- this.no_blocks = false;
- this.complexity = 0;
- }
- else
- {
- this.center_anchor = map.manhattan.FindNearMoveableNodeByBlock(sx, sy, sw, sh);
- //检测没有阻挡//
- this.no_blocks = map.manhattan.CheckNearExpectByBlock(sx, sy, sw, sh, false);
- //检测阻挡块数量//
- int bc = map.manhattan.GetNearExpectCountByBlock(sx, sy, sw, sh, true);
- this.complexity = map.manhattan.cell_sqrt * bc;
- }
- this.next_links.Clear();
- }
- internal void ResetNext()
- {
- if (this.center_anchor != null)
- {
- var near_table = GetNearTables(map.manhattan.IsInclined);
- foreach (var offset in near_table)
- {
- var next = map.getSpaceNode(CX + offset[0], CY + offset[1]);
- if (next != null && next.center_anchor != null)
- {
- if (this.center_anchor.AreaValue != next.center_anchor.AreaValue)
- {
- //两块区域不同(存在洞)//
- continue;
- }
- else if (this.no_blocks && next.no_blocks)
- {
- //两块都没有阻挡块,则不需要寻路//
- MWayPoint path = new MWayPoint(center_anchor);
- path.LinkNext(new MWayPoint(next.center_anchor));
- next_links.Put(next, new NextInfo(path));
- }
- else if (!map.manhattan.TouchMapLine(
- this.center_anchor.PosX,
- this.center_anchor.PosY,
- next.center_anchor.PosX,
- next.center_anchor.PosY))
- {
- //两块直接连线通过,则不需要寻路//
- MWayPoint path = new MWayPoint(center_anchor);
- path.LinkNext(new MWayPoint(next.center_anchor));
- next_links.Put(next, new NextInfo(path));
- }
- else
- {
- //两块之间寻路//
- MWayPoint path = map.manhattan.findPathInternal(this.center_anchor, next.center_anchor);
- if (path != null)
- {
- NextInfo info = new NextInfo(path);
- if (info.distance <= (map.space_full_cell_w + map.space_full_cell_h))
- {
- next_links.Put(next, info);
- }
- }
- }
- }
- }
- }
- this.nexts = new MSpaceNode[next_links.Count];
- this.next_links.Keys.CopyTo(nexts, 0);
- }
- internal void Clone(MSpaceNode data)
- {
- this.next_links.PutAll(data.next_links);
- this.nexts = new MSpaceNode[this.next_links.Count];
- this.next_links.Keys.CopyTo(this.nexts, 0);
- }
- public MWayPoint GetNextLink(MSpaceNode next)
- {
- var ret = next_links.Get(next);
- if (ret != null)
- {
- return ret.path;
- }
- return null;
- }
- public override bool TestCross(MapNode other)
- {
- return next_links.ContainsKey(other);
- }
- public override void Dispose()
- {
- next_links.Clear();
- nexts = null;
- }
- public override float GetG(MapNode target)
- {
- var t = (MSpaceNode)target;
- var ret = this.next_links.Get(t);
- if (ret != null)
- {
- return ret.distance + this.complexity;
- }
- else
- {
- float ndx = (t.AnchorNode.BX - this.AnchorNode.BX) * map.manhattan.cellw;
- float ndy = (t.AnchorNode.BY - this.AnchorNode.BY) * map.manhattan.cellh;
- return (float)Math.Sqrt((ndx * ndx) + (ndy * ndy)) + this.complexity;
- }
- }
- public override float GetH(MapNode father)
- {
- if (this == father)
- {
- return 0;
- }
- else
- {
- var t = (MSpaceNode)father;
- var ret = this.next_links.Get(t);
- if (ret != null)
- {
- return ret.distance + t.complexity;
- }
- else
- {
- return 0;
- }
- }
- }
- }
- public class MSpaceWayPoint : WayPoint
- {
- public MSpaceNode SpaceNode
- {
- get { return base.node as MSpaceNode; }
- }
- public MSpaceWayPoint Next
- {
- get { return base.next as MSpaceWayPoint; }
- }
- public MSpaceWayPoint Tail
- {
- get { return base.tail as MSpaceWayPoint; }
- }
- internal MSpaceWayPoint(MapNode map_node)
- : base(map_node)
- {
- }
- public override WayPoint Clone()
- {
- var ret = new MSpaceWayPoint(this.node);
- if (this.next != null)
- {
- ret.LinkNext(this.next.Clone());
- }
- return ret;
- }
- public AstarManhattan.MWayPoint ToLinkWayPoint()
- {
- if (next != null)
- {
- var ret = SpaceNode.GetNextLink(next.node as MSpaceNode);
- if (ret != null)
- {
- ret = ret.Clone() as AstarManhattan.MWayPoint;
- ret.Tail.LinkNext(this.Next.ToLinkWayPoint());
- return ret;
- }
- }
- return null;
- }
- }
- }
- }
- }
|