l

成都手游码农一枚
随笔 - 33, 文章 - 0, 评论 - 117, 引用 - 0
数据加载中……

[Unity3D] 菱形地图拼接渲染


1.大地图渲染(率土为1500*1500,每个格子大概400*200的贴图)
a)假设相机中心点为(x,y)
b)通过(x,y)计算出所在地图格子中心索引(j,i)
c)以(j,i)为中心w\h为长宽计算出需要显示的格子索引集合
d)渲染格子(并裁剪屏幕外的格子)
注意:率土地图有个20度绕x轴的俯视角度,所以裁剪区域要做相应的变化

 1 public void UpdateMap(Vector3 center)
 2 {
 3     // 遍历每一层并以此渲染
 4     for (var i = 0; i < _layerList.Count; ++i)
 5     {
 6         _layerList[i].UpdateLayer(center);
 7     }
 8 
 9     // 更新小地图
10     if (MapMiniMapHelper.Instance)
11     {
12         var x = (int)(center.x / (_tileWidth * 0.5f));
13         var y = (int)(center.y / _tileHeight);
14 
15         MapMiniMapHelper.Instance.UpdateMiniMap(x, y);
16     }
17 }
18 
19 public virtual void UpdateLayer(Vector3 center)
20 {
21     var mr = mapRenderer;
22     var cr = _halfRow;
23     var cc = _halfCol;
24     var ch = _tileHeight;
25     var cw = _tileWidth;
26 
27     var jj = 0;
28     var ii = 0;
29 
30     //   j + i = x / (w / 2)
31     // - j + i = y / (h / 2)
32     // =>
33     // i = (x / (w / 2) + y / (h / 2)) * 0.5
34     // j = (x / (w / 2) - y / (h / 2)) * 0.5
35     // 如果是菱形地图,那么计算如下
36     //jj = (int)((center.x / (_tileWidth * 0.5f) - center.y / (_tileHeight * 0.5f)) * 0.5f);
37     //ii = (int)((center.x / (_tileWidth * 0.5f) + center.y / (_tileHeight * 0.5f)) * 0.5f);
38     // 如果是交错四边形,那么计算如下
39     jj = (int)(center.x / (_tileWidth * 0.5f));
40     ii = (int)(center.y / _tileHeight);
41 
42     // dirty?
43     if (dirty == false && (_lastJJ == jj && _lastII == ii))
44     {
45         return;
46     }
47 
48     dirty = false;
49     _lastJJ = jj;
50     _lastII = ii;
51 
52     StartBuildSprite();
53 
54     for (var i = -cr; i <= cr; ++i)
55     {
56         for (var j = -cc; j <= cc; ++j)
57         {
58             // x = (j + i) * w / 2
59             // y = (i - j) * h / 2
60             // 如果是菱形地图,那么计算如下
61             // var position = new Vector3((jj + j + ii + i) * cw * 0.5f, (ii + i - jj - j) * ch * 0.5f, 0);
62             // 如果是交错四边形,那么计算如下
63             var position = new Vector3((jj + j) * cw * 0.5f, (ii + i + (Mathf.Abs(jj + j) % 2) * 0.5f) * ch, 0);
64 
65             // 裁剪多于格子
66             if (!mr._clipRect.Contains(position - center))
67             {
68                 continue;
69             }
70             
71             // 查询当前格子内容并显示
72             var sprite = mr.QuerySprite(index, jj + j, ii + i);
73 
74             if (sprite != null)
75             {
76                 BuildSprite(position, sprite, (index + 1) * 2000 - ((i + cr) * 2 + (jj + j) % 2) * (cc * 2 + 1) + (j + cc));
77             }
78         }
79     }
80 
81     StopBuildSprite();
82 }
2.水拼接算法(率土泥路算法和水一致)
a)将一个大格子分割成4个小格子(上下左右)
b)以此遍历每个小格子统计小格子周围8个小格子所在大格子是否为陆地
c)根据统计结果得出当前小格子除应该贴上哪种贴图

  1 /*如果是菱形地图,那么计算如下
  2 uint a = GenerateWaterEdge(2 * x, 2 * y + 1, 0) 
  3     | GenerateWaterEdge(2 * x + 1, 2 * y, 1) 
  4     | GenerateWaterEdge(2 * x, 2 * y, 2) 
  5     | GenerateWaterEdge(2 * x + 1, 2 * y + 1, 3);
  6 */
  7 // 如果是交错四边形,那么计算如下
  8 uint a = (uint)GenerateWaterEdge(2 * x + 1, 2 * y + (x % 2), 0)
  9     | (uint)GenerateWaterEdge(2 * x + 1, 2 * y + (x % 2) - 1, 1)
 10     | (uint)GenerateWaterEdge(2 * x + 0, 2 * y + (x % 2), 2)
 11     | (uint)GenerateWaterEdge(2 * x + 2, 2 * y + (x % 2)    , 3);
 12 
 13 int GenerateWaterEdge(int i, int j, int index)
 14 {
 15     var count = 0;
 16     var result = 0;
 17 
 18     /*如果是菱形地图,那么计算如下
 19     for (var x = i - 1; x <= i + 1; ++x)
 20     {
 21         for (var y = j - 1; y <= j + 1; ++y)
 22         {
 23             if (!IsWater(x / 2, y / 2))
 24             {
 25                 count++;
 26             }
 27         }
 28     }
 29     */
 30 
 31     // 如果是交错四边形,那么计算如下
 32     int[] xs  = new int[] { -2, -1, 0, 1, 2,  1,  0, -1};
 33     int[] ys0 = new int[] {  0,  0, 1, 0, 0, -1, -1, -1};
 34     int[] ys1 = new int[] {  0,  1, 1, 1, 0,  0, -1,  0 };
 35     bool[] sides = new bool[] { falsefalsefalsefalse };
 36 
 37     for (var n = 0; n < 8; ++n)
 38     {
 39         var x = i + xs[n];
 40         var y = j + ((i % 2 == 0) ? ys0[n] : ys1[n]);
 41 
 42         x = (int)Mathf.Floor(x / 2.0f);
 43         if (index == 0 && (n == 1 || n == 5))
 44         {
 45             x = x - 1;
 46         }
 47         if (index == 1 && (n == 3 || n == 7))
 48         {
 49             x = x - 1;
 50         }
 51         if (index == 2 && (n == 0 || n == 2 || n == 4 || n == 6))
 52         {
 53             x = x - 1;
 54         }
 55 
 56         if (index == 0 && (n == 0 || n == 2 || n == 4 || n == 6))
 57         {
 58             y = y + 1;
 59         }
 60         if (index == 2 && (n == 1 || n == 5))
 61         {
 62             y = y + 1;
 63         }
 64         if (index == 3 && (n == 3 || n == 7))
 65         {
 66             y = y + 1;
 67         }
 68         y = (int)Mathf.Floor((y - (x % 2)) / 2.0f);
 69 
 70         if (!IsWater(x, y))
 71         {
 72             if ((index == 0 && n == 3) || (index == 3 && n == 3))
 73             {
 74                 sides[0] = true;
 75             }
 76             if ((index == 1 && n == 7) || (index == 2 && n == 7))
 77             {
 78                 sides[1] = true;
 79             }
 80             if ((index == 2 && n == 1) || (index == 0 && n == 1))
 81             {
 82                 sides[2] = true;
 83             }
 84             if ((index == 3 && n == 5) || (index == 1 && n == 5))
 85             {
 86                 sides[3] = true;
 87             }
 88             count++;
 89         }
 90     }
 91 
 92     if (count == 1) // 缺角:只有一个陆地块
 93     {
 94         result = 1;
 95     }
 96     else if (count == 3) // 直边:某一边是水
 97     {
 98         /*如果是菱形地图,那么计算如下
 99         if (!IsWater((i) / 2, (j + 1) / 2))
100         {
101             result = 2;
102         }
103 
104         if (!IsWater((i) / 2, (j - 1) / 2))
105         {
106             result = 3;
107         }
108 
109         if (!IsWater((i - 1) / 2, (j) / 2))
110         {
111             result = 4;
112         }
113 
114         if (!IsWater((i + 1) / 2, (j) / 2))
115         {
116             result = 5;
117         }
118         */
119         // 如果是交错四边形,那么计算如下
120         if (sides[0])
121         {
122             result = 2;
123         }
124 
125         if (sides[1])
126         {
127             result = 3;
128         }
129 
130         if (sides[2])
131         {
132             result = 4;
133         }
134 
135         if (sides[3])
136         {
137             result = 5;
138         }
139     }
140     else if (count == 4) // 夹角:类似><这种形状
141     {
142         if (index == 1)
143         {
144             result = 6;
145         }
146         else if (index == 2)
147         {
148             result = 6;
149         }
150     }
151     else if (count == 5) // 转角:只有一个角是水
152     {
153         result = 7;
154     } 
155 
156     // 方便存储的合成
157     return result << ((index) * 3);
158 }
159 
160 public override void UpdateLayer(Vector3 center)
161 {
162     var mr = mapRenderer;
163     var cr = _halfRow;
164     var cc = _halfCol;
165     var ch = _tileHeight;
166     var cw = _tileWidth;
167 
168     var jj = 0;
169     var ii = 0;
170 
171     //   j + i = x / (w / 2)
172     // - j + i = y / (h / 2)
173     // =>
174     // i = (x / (w / 2) + y / (h / 2)) * 0.5
175     // j = (x / (w / 2) - y / (h / 2)) * 0.5
176     //jj = (int)((center.x / (_tileWidth * 0.5f) - center.y / (_tileHeight * 0.5f)) * 0.5f);
177     //ii = (int)((center.x / (_tileWidth * 0.5f) + center.y / (_tileHeight * 0.5f)) * 0.5f);
178     jj = (int)(center.x / (_tileWidth * 0.5f));
179     ii = (int)(center.y / _tileHeight);
180 
181     // dirty?
182     if (dirty == false && (_lastJJ == jj && _lastII == ii))
183     {
184         return;
185     }
186 
187     dirty = false;
188     _lastJJ = jj;
189     _lastII = ii;
190 
191     StartBuildSprite();
192 
193     for (var i = -cr; i <= cr; ++i)
194     {
195         for (var j = -cc; j <= cc; ++j)
196         {
197             var value = mr.QueryValue(jj + j, ii + i);
198 
199             if ((value & 0x80000000) != 0)
200             {
201                 var key = (value & 0x0FFF);
202                 var offset = 0;
203                 var layer = (value & 0x78000000) >> 27;
204 
205                 if (layer == (int)MapRenderer.Layer.Water)
206                 {
207                     // x = (j + i) * w / 2
208                     // y = (i - j) * h / 2
209                     //var lx = (jj + j + ii + i) * cw * 0.5f;
210                     //var ly = (ii + i - jj - j) * ch * 0.5f;
211                     var lx = (jj + j) * cw * 0.5f;
212                     var ly = (ii + i + (Mathf.Abs(jj + j) % 2) * 0.5f) * ch;
213 
214                     // 取出每个格子的状态值来判断
215                     offset = ((value & 0x7000) >> 12) * 26;
216                     switch (key & 0x7) // 上边的小格子
217                     {
218 
219                                         //地图 中心点 贴图索引 坐标X 坐标Y
220                         case 1: AddSprite(mr, ref center, offset + 9, lx - cw * 0.25f, ly + ch * 0.5f);
221                                 AddSprite(mr, ref center, offset + 10, lx, ly + ch * 0.25f);
222                                 AddSprite(mr, ref center, offset + 11, lx + cw * 0.25f, ly + ch * 0.5f); break;
223                         case 2: AddSprite(mr, ref center, offset + 2, lx, ly + ch * 0.25f); break;
224                         case 4: AddSprite(mr, ref center, offset + 5, lx, ly + ch * 0.25f); break;
225                         case 7: AddSprite(mr, ref center, offset + 21, lx, ly + ch * 0.25f); break;
226                     }
227 
228                     offset = ((value & 0x1C0000) >> 18) * 26;
229                     switch ((key >> 6) & 0x7) // 左边的小格子
230                     {
231                         case 1: AddSprite(mr, ref center, offset + 15, lx - cw * 0.5f, ly + ch * 0.25f);
232                                 AddSprite(mr, ref center, offset + 16, lx - cw * 0.25f, ly);
233                                 AddSprite(mr, ref center, offset + 17, lx - cw * 0.5f, ly - ch * 0.25f); break;
234                         case 3: AddSprite(mr, ref center, offset + 3, lx - cw * 0.25f, ly); break;
235                         case 4: AddSprite(mr, ref center, offset + 6, lx - cw * 0.25f, ly); break;
236                         case 6: AddSprite(mr, ref center, offset + 25, lx - cw * 0.5f, ly); break;
237                         case 7: AddSprite(mr, ref center, offset + 23, lx - cw * 0.25f, ly); break;
238                     }
239 
240                     offset = ((value & 0xE00000) >> 21) * 26;
241                     switch ((key >> 9) & 0x7) // 右边的小格子 
242                     {
243                         case 1: AddSprite(mr, ref center, offset + 18, lx + cw * 0.5f, ly + ch * 0.25f);
244                                 AddSprite(mr, ref center, offset + 19, lx + cw * 0.25f, ly);
245                                 AddSprite(mr, ref center, offset + 20, lx + cw * 0.5f, ly - ch * 0.25f); break;
246                         case 2: AddSprite(mr, ref center, offset + 1, lx + cw * 0.25f, ly); break;
247                         case 5: AddSprite(mr, ref center, offset + 8, lx + cw * 0.25f, ly); break;
248                         case 7: AddSprite(mr, ref center, offset + 24, lx + cw * 0.25f, ly); break;
249                     }
250 
251                     offset = ((value & 0x38000) >> 15) * 26;
252                     switch ((key >> 3) & 0x7) // 下边的小格子
253                     {
254                         case 1: AddSprite(mr, ref center, offset + 12, lx - cw * 0.25f, ly - ch * 0.5f);
255                             AddSprite(mr, ref center, offset + 13, lx, ly - ch * 0.25f);
256                             AddSprite(mr, ref center, offset + 14, lx + cw * 0.25f, ly - ch * 0.5f); break;
257                         case 3: AddSprite(mr, ref center, offset + 4, lx, ly - ch * 0.25f); break;
258                         case 5: AddSprite(mr, ref center, offset + 7, lx, ly - ch * 0.25f); break;
259                         case 6: AddSprite(mr, ref center, offset + 26, lx, ly - ch * 0.5f); break;
260                         case 7: AddSprite(mr, ref center, offset + 22, lx, ly - ch * 0.25f); break;
261                     }
262                 }
263             }
264         }
265     }
266 
267     StopBuildSprite();
268 }
3.城墙(与水拼接类似)
效果:







posted on 2016-05-16 20:09 l1989 阅读(2128) 评论(4)  编辑 收藏 引用 所属分类: 游戏

评论

# re: [Unity3D] 菱形地图拼接渲染  回复  更多评论   

支持一下,就是感觉代码不清爽。
2016-05-18 11:46 | GLimix

# re: [Unity3D] 菱形地图拼接渲染  回复  更多评论   

@GLimix
是的,太随意了 ^^
2016-05-19 09:12 | l1989

# re: [Unity3D] 菱形地图拼接渲染  回复  更多评论   

看起来有点复杂,大神介不介意给个demo,让我自己跑跑,学习学习
2016-07-25 22:56 | man

# re: [Unity3D] 菱形地图拼接渲染[未登录]  回复  更多评论   

@man
目前没有,代码在公司
2016-08-17 00:06 | l1989

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理