遊戲中的隨機地形生成演算法(三)
阿新 • • 發佈:2019-02-12
在上篇教程中,我們已經把Map中的每個點都實實在在的畫了出來,四個點形成一個正方形。其中,正方形的每條邊都有一箇中點。
那麼,這節課我們來把該連在一起的點連起來,繪製我們的mesh。
public class Square { public ControlNode topLeft, topRight, bottomLeft, bottomRight; //一個矩形擁有四個控制節點 public Node centerTop, centerLeft, centerRight, centerBottom; //還有四個節點 public int configuration; public Square(ControlNode _topLeft, ControlNode _topRight, ControlNode _bottomLeft, ControlNode _bottomRight) //我們只需要定義四個控制節點 { topLeft = _topLeft; topRight = _topRight; bottomLeft = _bottomLeft; bottomRight = _bottomRight; //控制節點包含節點 centerTop = topLeft.right; centerBottom = bottomLeft.right; centerLeft = bottomLeft.above; centerRight = bottomRight.above; if (topLeft.isActive) configuration += 8; if (topRight.isActive) configuration += 4; if (bottomRight.isActive) configuration += 2; if (bottomLeft.isActive) configuration += 1; } }
首先完善一下我們的Square類,增加了一個int變數configuration,我們用它來記錄當前矩形控制節點的啟用情況,
如果左上啟用:對應1000=8,
如果右上啟用:對應0100=4;
如果左下啟用:對應0010=2;
如果右下啟用:對應0001=1;
然後我們定義一個分形函式TriangulateSquare,顧名思義,用來把一個Square分割成三角形。
在這裡,我們使用到了剛剛定義的configuration來分辨16種情形,在每種情形中,我們又使用了MeshFromPoints這個方法來構建mesh。void TriangulateSquare(Square square) { switch (square.configuration) { //1 point case 1: MeshFromPoints(square.centerBottom, square.bottomLeft, square.centerLeft); break; case 2: MeshFromPoints(square.centerRight, square.bottomRight, square.centerBottom); break; case 4: MeshFromPoints(square.centerTop, square.topRight, square.centerRight); break; case 8: MeshFromPoints(square.topLeft, square.centerTop, square.centerLeft); break; //2 points case 3: MeshFromPoints(square.centerRight, square.bottomRight, square.bottomLeft, square.centerLeft); break; case 6: MeshFromPoints(square.centerTop, square.topRight, square.bottomRight, square.centerBottom); break; case 9: MeshFromPoints(square.topLeft, square.centerTop, square.centerBottom, square.bottomLeft); break; case 12: MeshFromPoints(square.topLeft, square.topRight, square.centerRight, square.centerLeft); break; case 5: MeshFromPoints(square.centerTop, square.topRight, square.centerRight, square.centerBottom, square.bottomLeft, square.centerLeft); break; case 10: MeshFromPoints(square.topLeft, square.centerTop, square.centerRight, square.bottomRight, square.centerBottom, square.centerLeft); break; // 3 point: case 7: MeshFromPoints(square.centerTop, square.topRight, square.bottomRight, square.bottomLeft, square.centerLeft); break; case 11: MeshFromPoints(square.topLeft, square.centerTop, square.centerRight, square.bottomRight, square.bottomLeft); break; case 13: MeshFromPoints(square.topLeft, square.topRight, square.centerRight, square.centerBottom, square.bottomLeft); break; case 14: MeshFromPoints(square.topLeft, square.topRight, square.bottomRight, square.centerBottom, square.centerLeft); break; // 4 point: case 15: MeshFromPoints(square.topLeft, square.topRight, square.bottomRight, square.bottomLeft); break; } }
void MeshFromPoints(params Node[] nodes) { AssignVerticals(nodes);//在建立三角形之前,先儲存一下它的頂點資訊 if (nodes.Length>=3) { CreateTriangle(nodes[0], nodes[1], nodes[2]); } if (nodes.Length >= 4) { CreateTriangle(nodes[0], nodes[2], nodes[3]); } if (nodes.Length >= 5) { CreateTriangle(nodes[0], nodes[3], nodes[4]); } if (nodes.Length >= 6)//如果有6個點,那我們需要建立4個三角形 { CreateTriangle(nodes[0], nodes[4], nodes[5]); } } void AssignVerticals(Node[] points) { for (int i = 0; i < points.Length;i++ ) { if (points[i].vertexIndex==-1) { points[i].vertexIndex = verticals.Count; verticals.Add(points[i].position); } } } void CreateTriangle(Node a, Node b, Node c) { triangles.Add(a.vertexIndex); triangles.Add(b.vertexIndex); triangles.Add(c.vertexIndex); }
你也許已經注意到了,我們還沒有定義verticals和triangles,把它們定義為類的欄位:
List<Vector3> verticals;
List<int> triangles;
就快完成了!現在給我們的遊戲物體掛上Mesh Filter和Mesh Renderer元件,同時建立一個黑色的Material材質球,掛載到Mesh Renderer元件裡的Materail陣列中。
接著我們把MeshGenerator中的OnGizmosDraw函式註釋掉,已經不需要它啦~
同時修改以下程式碼:
public void GenerateMesh(int[,] map, int squareSize)
{
squareGrid = new SquareGrid(map, squareSize);
verticals=new List<Vector3>();
triangles=new List<int>();
for (int x = 0; x < squareGrid.squares.GetLength(0); x++)
{
for (int y = 0; y < squareGrid.squares.GetLength(1); y++)
{
TriangulateSquare(squareGrid.squares[x, y]);
}
}
Mesh mesh=new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
mesh.vertices=verticals.ToArray();
mesh.triangles=triangles.ToArray();
mesh.RecalculateNormals();
}
我們使用程式碼手動定義了一個mesh元件。好,到現在已經完成了,我們來執行看下,希望不會出錯:
喔噢!大功告成,簡直不能再棒了!