using CommonAI.RTS.Manhattan; using CommonLang; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; namespace CommonAI.Zone.Helper { public class ZoneManhattanMap : Disposable, IManhattanMap { public ZoneInfo Data { get; private set; } public int[,] Terrain { get; private set; } readonly private float TotalW, TotalH; readonly private HashMap Brushes; public ZoneManhattanMap(ZoneInfo info, TerrainDefinitionMap define) { this.Data = info; this.TotalW = info.TotalWidth; this.TotalH = info.TotalHeight; this.Terrain = info.TerrainMatrix; this.Brushes = new HashMap((define != null) ? define.Brushes.Count : 0); if (define != null) { foreach (var b in define.Brushes) { Brushes.Put(b.Value, b); } } } protected override void Disposing() { Brushes.Clear(); Data = null; Terrain = null; } public int XCount { get { return Data.mXCount; } } public int YCount { get { return Data.mYCount; } } public float CellW { get { return Data.mGridCellW; } } public float CellH { get { return Data.mGridCellH; } } public float TotalWidth { get { return TotalW; } } public float TotalHeight { get { return TotalH; } } public virtual bool TestBlock(int bx, int by) { TerrainDefinitionMap.MapBlockBrush brush; if (Terrain[bx, by] != 0) { if (Brushes.TryGetValue(Terrain[bx, by], out brush)) { return brush.IsBlock; } return true; } return false; } public bool TestBlockValue(int value) { TerrainDefinitionMap.MapBlockBrush brush; if (value != 0) { if (Brushes.TryGetValue(value, out brush)) { return brush.IsBlock; } return true; } return false; } public virtual int GetValue(int bx, int by) { return Terrain[bx, by]; } public virtual bool SetValue(int bx, int by, int value) { if (value != Terrain[bx, by]) { Terrain[bx, by] = value; return true; } return false; } public virtual AstarManhattan.MMapNode CreateMapNode() { return new ZoneMapNode(); } } public class ZoneMapNode : AstarManhattan.MMapNode { private BindArea bind_area; public ZoneClient.ZoneEditorArea ClientArea { get { return (bind_area == null) ? null : bind_area.client_area; } } public Instance.ZoneArea ServerArea { get { return (bind_area == null) ? null : bind_area.server_area; } } public void SetClientArea(ZoneClient.ZoneEditorArea area) { if (bind_area == null) { bind_area = new BindArea(); } bind_area.client_area = area; } public void SetServerArea(Instance.ZoneArea area) { if (bind_area == null) { bind_area = new BindArea(); } bind_area.server_area = area; } public class BindArea { public ZoneClient.ZoneEditorArea client_area; public Instance.ZoneArea server_area; } } public class ManhattanMapAreaGenerator { public class MapNodeIndex { public readonly int BX; public readonly int BY; public MapNodeIndex(int bx, int by) { this.BX = bx; this.BY = by; } public override bool Equals(object obj) { if (obj is MapNodeIndex) { var src = (MapNodeIndex)obj; return src.BX == this.BX && src.BY == this.BY; } return base.Equals(obj); } public override int GetHashCode() { return base.GetHashCode(); } } /// /// 扫描地块区域结果 /// public class ContinuousMapNode : IEnumerable { private readonly ZoneInfo map; private readonly int bsx, bsy, bdx, bdy; private readonly int value; private readonly List nodes; private readonly MapNodeIndex[,] node_matrix; public int Value { get { return value; } } internal ContinuousMapNode(ZoneInfo map, int bx, int by, int xr, int yr) { this.map = map; this.value = map.TerrainMatrix[bx, by]; this.nodes = new List(); this.bsx = bx - xr; this.bsy = by - yr; this.bdx = bx + xr; this.bdy = by + yr; this.node_matrix = new MapNodeIndex[xr + 1 + xr, yr + 1 + yr]; } public bool IsInRect(int bx, int by) { if (bx >= this.bsx && bx <= this.bdx && by >= this.bsy && by <= this.bdy) { return true; } return false; } public bool IsInRect(float x, float y) { int bx = (int)(x / map.GridCellW); int by = (int)(y / map.GridCellH); return IsInRect(bx, by); } public MapNodeIndex GetIndex(int bx, int by) { if (IsInRect(bx, by)) { return node_matrix[bx - bsx, by - bsy]; } return null; } public bool Contains(MapNodeIndex src) { return GetIndex(src.BX, src.BY) != null; } public bool TryAdd(MapNodeIndex src) { if (IsInRect(src.BX, src.BY) && (node_matrix[src.BX - bsx, src.BY - bsy] == null)) { nodes.Add(src); node_matrix[src.BX - bsx, src.BY - bsy] = src; return true; } return false; } public IEnumerator GetEnumerator() { return nodes.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return nodes.GetEnumerator(); } } private static int[][] near_table_cross = new int[][] { new int[]{ 0,-1}, new int[]{-1, 0}, new int[]{ 1, 0}, new int[]{ 0, 1}, }; private ZoneInfo map; public ManhattanMapAreaGenerator(ZoneInfo map) { this.map = map; } public bool TryGetValue(int bx, int by, out int value) { if (bx >= 0 && bx < map.XCount && by >= 0 && by < map.YCount) { value = map.TerrainMatrix[bx, by]; return true; } value = 0; return false; } public bool TryGetValue(float x, float y, out int value) { int bx = (int)(x / map.GridCellW); int by = (int)(y / map.GridCellH); return TryGetValue(bx, by, out value); } public bool TryGetIndex(int bx, int by, int value, out MapNodeIndex index) { if (bx >= 0 && bx < map.XCount && by >= 0 && by < map.YCount && map.TerrainMatrix[bx, by] == value) { index = new MapNodeIndex(bx, by); return true; } index = new MapNodeIndex(-1, -1); return false; } public bool TryGetIndex(float x, float y, int value, out MapNodeIndex index) { int bx = (int)(x / map.GridCellW); int by = (int)(y / map.GridCellH); return TryGetIndex(bx, by, value, out index); } /// /// /// /// 中心点 /// 中心点 /// x半径 /// y半径 /// public ContinuousMapNode GetContinuousMapNode(float x, float y, float xr, float yr) { return GetContinuousMapNode( (int)(x / map.GridCellW), (int)(y / map.GridCellH), (int)(xr / map.GridCellW), (int)(yr / map.GridCellH)); } public virtual ContinuousMapNode GetContinuousMapNode(int bx, int by, int xr, int yr) { if (bx >= 0 && bx < map.XCount && by >= 0 && by < map.YCount) { ContinuousMapNode list = new ContinuousMapNode(map, bx, by, xr, yr); MapNodeIndex src = new MapNodeIndex(bx, by); if (list.TryAdd(src)) { Stack stack = new Stack((xr * 2) * (yr * 2)); stack.Push(src); while (stack.Count > 0) { MapNodeIndex cur = stack.Pop(); for (int i = 0; i < near_table_cross.Length; i++) { MapNodeIndex next; if (TryGetIndex(cur.BX + near_table_cross[i][0], cur.BY + near_table_cross[i][1], list.Value, out next)) { if (list.TryAdd(next)) { stack.Push(next); } } } } return list; } } return null; } } }