控制地图显示范围

 1  private void ControlDisplayArea(Vector3 pos, bool IsInit)
 2     {
 3 
 4         IntVector2 newcoord = GetCoord(pos);//新得到的地图下标
 5         if (IsInit)//如果为初始化显示
 6         {
 7             ControlDisplayAll(false);
 8             int x_min = newcoord.x - area >= 0 ? newcoord.x - area : 0;
 9             int y_min = newcoord.y - area >= 0 ? newcoord.y - area : 0;
10             int x_max = newcoord.x + area <= size_x - 1 ? newcoord.x + area : size_x - 1;
11             int y_max = newcoord.y + area <= size_z - 1 ? newcoord.y + area : size_z - 1;
12             for (int i = y_min; i <= y_max; i++)
13                 for (int j = x_min; j <= x_max; j++)
14                 {
15                     if (GetOrder(j, i) != -1)
16                         map.GetChild(GetOrder(j, i)).gameObject.SetActive(true);
17                 }
18             return;
19         }
20         if (newcoord == oldcoord)//如果对象下标未更新
21             return;
22         int index;//计算下标的辅助变量
23         if (newcoord.x - oldcoord.x != 0)//左右方向更新
24         {
25             bool IsLeft = newcoord.x - oldcoord.x < 0 ? true : false;
26 
27             for (int i = newcoord.y - area; i <= newcoord.y + area; i++)//生成按新坐标边界
28             {
29                 index = GetOrder(IsLeft ? newcoord.x - area : newcoord.x + area, i);
30                 if (index != -1)
31                     map.GetChild(index).gameObject.SetActive(true);
32             }
33             for (int j = oldcoord.y - area; j <= oldcoord.y + area; j++)//消去按旧坐标边界
34             {
35                 index = GetOrder(IsLeft ? oldcoord.x + area : oldcoord.x - area, j);
36                 if (index != -1)
37                     map.GetChild(index).gameObject.SetActive(false);
38             }
39         }
40 
41         if (newcoord.y - oldcoord.y != 0)//上下方向更新
42         {
43             bool IsUp = newcoord.y - oldcoord.y > 0 ? true : false;
44 
45             for (int i = newcoord.x - area; i <= newcoord.x + area; i++)//生成按新坐标边界
46             {
47                 index = GetOrder(i, IsUp ? newcoord.y + area : newcoord.y - area);
48                 if (index != -1)
49                     map.GetChild(index).gameObject.SetActive(true);
50             }
51             for (int j = oldcoord.x - area; j <= oldcoord.x + area; j++)
52             {
53                 index = GetOrder(j, IsUp ? oldcoord.y - area : oldcoord.y + area);
54                 if (index != -1)
55                     map.GetChild(index).gameObject.SetActive(false);//消去按旧坐标边界
56             }
57         }
58         oldcoord = newcoord;
59     }

 

新的方法的原理。每次对象坐标改变时,先记录下改变前其n圈内的格子坐标,然后算出改变后n圈内的格子坐标,后者全部setActive(true).后者减去前者作为显示对象。前者减去后者作为隐藏对象

  1 using System.Collections;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using UnityEngine;
  5 
  6 public class Control_Area : MonoBehaviour
  7 {
  8     
  9     public Transform mPlayer;//监控对象
 10     public Transform mMap;//地图
 11     public int mMaxRow;//最大行数
 12     public int mMaxCol;//最大列数
 13     public int mSize;//chunk尺寸,用来计算目标所在坐标
 14     public int Area=3;//显示范围
 15     //坐标类
 16 
 17     private Coordinate CurCoord = new Coordinate(-99,-99);
 18     private List<Coordinate> curCbs = null;//用来显示范围内的格子
 19     private List<Coordinate> preCbs = null;//用来消去上次范围内但不在现范围内的格子
 20 
 21 
 22     /// <summary>
 23     /// 用来初始化参数
 24     /// </summary>
 25     /// <param name="max_row"></param>
 26     /// <param name="max_col"></param>
 27     /// <param name="size"></param>
 28     /// <param name="map"></param>
 29     /// <returns></returns>
 30     public void Init(int max_row, int max_col,int size,Transform map)
 31     {
 32         mMaxRow = max_row;
 33         mMaxCol = max_col;
 34         mSize = size;
 35         mMap = map;
 36     }
 37 
 38     public void Start()
 39     { 
 40         //初始化时隐藏所有chunk
 41         for (int i = 0; i < mMap.childCount; i++)
 42         {
 43             Transform tf = mMap.GetChild(i);
 44             tf.gameObject.SetActive(false);
 45         }
 46         InvokeRepeating("ChunkPositionUpdate", 0f, 1f);
 47     }
 48 
 49     /// <summary>
 50     /// 更新位置,允许超出范围
 51     /// </summary>
 52     /// <returns></returns>
 53     public void ChunkPositionUpdate()
 54     {
 55         if (mPlayer == null || mMap == null)
 56         {
 57             return;
 58         }
 59         //将人物的世界坐标变换为地图的局部坐标
 60         Vector3 localHeroPos = mMap.transform.InverseTransformPoint(mPlayer.transform.position);
 61 
 62         int col = (int)(localHeroPos.x / mSize);
 63         int row = (int)(localHeroPos.z / mSize);
 64 
 65        //如果仍然处于旧位置
 66         if (CurCoord.Row == row && CurCoord.Col == col)
 67         {
 68             return;
 69         }
 70         //先把旧的周围所有圈方块记录下来
 71         preCbs = null;
 72         curCbs = null;
 73         preCbs = new List<Coordinate>();
 74         curCbs = new List<Coordinate>();
 75         for (int i = 0; i <Area; ++i)
 76         {
 77             preCbs.AddRange(new List<Coordinate>(GetCoordInR(CurCoord.Row, CurCoord.Col, i)));
 78         }
 79 
 80         CurCoord.Row = row;
 81         CurCoord.Col = col;
 82         ChunkVisibleUpdate();
 83     }
 84 
 85     /// <summary>
 86     /// 获取ChunkID
 87     /// </summary>
 88     /// <param name="row"></param>
 89     /// <param name="col"></param>
 90     /// <returns>int</returns>
 91     public int GetChunkID(int row,int col)
 92     {
 93         return row * mMaxCol + col;
 94     }
 95 
 96     /// <summary>
 97     /// 更新可见度
 98     /// </summary>
 99     /// <returns></returns>
100     public void ChunkVisibleUpdate()
101     {
102         for (int i = 0; i < Area; ++i)
103         {
104             Coordinate[] cbs = GetCoordInR(CurCoord.Row, CurCoord.Col, i);
105             curCbs.AddRange(new List<Coordinate>(cbs)); 
106         }
107         List<Coordinate> display = new List<Coordinate>(curCbs.ToArray());//显示的新格子
108         List<Coordinate> hide = new List<Coordinate>(preCbs.ToArray());//消去的旧格子
109         for (int i = curCbs.Count-1; i >=0; i--)
110         {
111             for (int j = preCbs.Count-1; j>=0;j--)
112             {
113                 if (Coordinate.Equal(curCbs[i],preCbs[j]))
114                 {
115                     display[i] = null;
116                     hide[j] = null;
117                 }
118             }
119         }
120 
121         display.RemoveAll(item =>{ return item == null; });//消去为null的坐标,这里指新坐标和旧坐标公有的格子
122         hide.RemoveAll(item => { return item == null; });
123 
124         for (int i = 0; i < display.Count; ++i)
125         {
126             mMap.GetChild(GetChunkID(display[i].Row, display[i].Col)).gameObject.SetActive(true);
127         }
128 
129         for (int i = 0; i < hide.Count; ++i)
130         {
131             mMap.GetChild(GetChunkID(hide[i].Row, hide[i].Col)).gameObject.SetActive(false);
132         }
133 
134     }
135 
136 
137     /// <summary>
138     /// 返回地图范围内的坐标
139     /// </summary>
140     /// <param name="i"></param>
141     /// <param name="j"></param>
142     /// <returns>Coordinate</returns>
143     private Coordinate GetValidCoord(int i, int j)
144     {
145         if (i < 0 || i >= mMaxRow || j < 0 || j >= mMaxCol)
146         {
147             return null;
148         }
149         return new Coordinate(i,j);
150     }
151 
152 
153 
154     /// <summary>
155     /// 返回返回指定第几围的坐标,若是超出范围则被排除在外
156     /// </summary>
157     /// <param name="row"></param>
158     /// <param name="col"></param>
159     /// <param name="r"></param>
160     /// <returns>Coordinate[]</returns>
161     private Coordinate[] GetCoordInR(int row, int col, int r)
162     {
163         List<Coordinate> list = new List<Coordinate>();
164         for (int i = 0; i < 2 * r + 1; ++i)
165         {
166             Coordinate cb = GetValidCoord(row - r, col - r + i);
167             if (cb != null && !list.Contains(cb))
168             {
169                 list.Add(cb);
170             }
171             cb = GetValidCoord(row - r + i, col - r);
172             if (cb != null && !list.Contains(cb))
173             {
174                 list.Add(cb);
175             }
176             cb = GetValidCoord(row + r, col - r + i);
177             if (cb != null && !list.Contains(cb))
178             {
179                 list.Add(cb);
180             }
181             cb = GetValidCoord(row - r + i, col + r);
182             if (cb != null && !list.Contains(cb))
183             {
184                 list.Add(cb);
185             }
186         }
187         return list.ToArray();
188     }
189 
190     /// <summary>
191     /// 坐标类
192     /// </summary>
193     class Coordinate
194     {
195         public int Row;
196         public int Col;
197         public Coordinate(int row, int col)
198         {
199             Row = row;
200             Col = col;
201         }
202         public Coordinate(Coordinate m)
203         {
204             Row = m.Row;
205             Col = m.Col;
206         }
207         public static bool Equal(Coordinate a, Coordinate b)
208         {
209             if (a.Col == b.Col && a.Row == b.Row)
210                 return true;
211             else
212                 return false;
213         }
214     }
215 }
修正(上面那个瞬间移动的话会出现为未显示区域)

 

posted @ 2017-04-10 10:40  露夕逝  阅读(416)  评论(0编辑  收藏  举报