游戏中的随机地形生成算法(三)

xiaoxiao2021-02-28  30

在上篇教程中,我们已经把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分割成三角形。

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; } }

在这里,我们使用到了刚刚定义的configuration来分辨16种情形,在每种情形中,我们又使用了MeshFromPoints这个方法来构建mesh。

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组件。好,到现在已经完成了,我们来运行看下,希望不会出错:

喔噢!大功告成,简直不能再棒了!

转载请注明原文地址: https://www.6miu.com/read-1400242.html

最新回复(0)