程序图生成 - 确定相邻的图块

时间:2016-03-28 14:29:31

标签: c# list procedural-generation

我最初使用2d数组“Tile”来存储程序生成的地图及其各种内容。

每个瓷砖包含一个相邻的列表,允许每个瓷砖知道哪个顶点最接近它,在8个不同的边(直线相邻和对角线相邻)上触摸它。

一般的想法取自Amit的多边形地图生成,但我试图通过使用网格设置而不是voronois来简化它,但是我遇到了比我原先认为的可能更多的麻烦。当我废弃2d阵列时,我目前的困境是找出邻接关系。

在更改为列表之前,我就是这样做的:

private void ConstructAdjacencyList() {

    // Create Adjacency List
    for (int x = 0; x < mapWidth; x++) {
        for (int y = 0; y < mapHeight; y++) {
            // Bool to find position of point
            bool omitLeft = false;      bool omitRight = false;
            bool omitTop = false;       bool omitBottom = false;
            // Enable bools based on position, reset on each loop               
            if (x == 0)
                omitLeft = true;                
            else if (x == mapWidth - 1)
                omitRight = true;               
            if (y == 0)
                omitTop = true;             
            else if (y == mapHeight - 1)
                omitBottom = true;

            // Add entries to list based on bool settings
            if (!omitLeft) {
                // Left center
                islandMap[x,y].adjacent.Add(islandMap[x-1,y]);
                if (!omitTop)
                    islandMap[x,y].adjacent.Add(islandMap[x-1,y-1]);
                if (!omitBottom)
                    islandMap[x,y].adjacent.Add(islandMap[x-1,y+1]);
            }

            if (!omitTop) // Top Center
                islandMap[x,y].adjacent.Add(islandMap[x,y-1]);
            if (!omitBottom) // Bottom Center
                islandMap[x,y].adjacent.Add(islandMap[x,y+1]);

            if (!omitRight) {
                // Right Center
                islandMap[x,y].adjacent.Add(islandMap[x+1,y]);
                if (!omitTop)
                    islandMap[x,y].adjacent.Add(islandMap[x+1,y-1]);
                if (!omitBottom)
                    islandMap[x,y].adjacent.Add(islandMap[x+1,y+1]);
            }               
        }
    } // End Adjacency

    Debug.Log ("Adjacencies Built");
}

x,y值现在保存在islandMap.point(存储x和y值的Vector 2d,如下所示:)

public MapController() {
    width = height = (int)Mathf.Sqrt (tileCount);

    // Lists for points
    var points = new List<Vector2>();

    // Build a random set of points.
    for (float x = 0; x < width; x++)   {
        for (float y = 0; y < height; y++)  {
            points.Add(new Vector2(x,y));
        }
    }

    map = new Map (points, width, height, lakeTreshold);
}

地图本身目前有以下内容:

public class Map {
   Func<Vector2, bool> inside; // Contains function to randomly seed area
   bool needsMoreRandomness;

   public List<Tile> islandMap; // Previously was Tile[,] islandMap
   public int mapWidth { get; private set; } // Calculated as Sqrt(totalPoints)
   public int mapHeight { get; private set; }

与其他方法一起使用,例如ConstructAdjacencyList()方法,我目前仍然坚持。

那么如何在不依赖阵列定位的情况下继续构建周围点的邻接列表呢?我可以暂时从数组中引用整个列表,在这个2d数组中放置对整个列表中每个磁贴的引用,设置邻接然后删除数组而不丢失信息吗?我相信它只会使用引用,所以它应该没问题...每个tile包含一个索引来存储它的构建顺序,如下所示:

foreach (var point in points) {
        var p = new Tile { index = islandMap.Count, point = point };
        p.border = point.x == 0 || point.x == mapWidth || point.y == 0 || point.y == mapHeight;
        islandMap.Add (p);
        tileLookup[point] = p;
    }

对不起,如果这太长了......我只是意识到它非常庞大 - .-

2 个答案:

答案 0 :(得分:0)

假设您没有做任何事情来搞乱点数的顺序,您可以处理1D list/array as 2D list/array。我链接的示例是在C中,但是与语言无关。

话虽如此,假设您在初始化过程中只打算这样做一次。鉴于点数相对较少,你可以通过一个循环遍历点列表的函数轻松地强制它。根据需要挑选邻居。我的C#有点生疏,但我正在谈论这样的事情:

private List<Vector2> getAdjacenctPointList(List<Vector2> pointsList, Vector2 point){
  var adjacencyList = new List<Vector2>();
  foreach (var pt in pointList){
    var offset = Math.abs(pt.x - point.x) + Math.abs(pt.y - point.y);
    if(offset > 0 && offset <= 1.0){
      adjacencyList.add(pt);
    }
  }
  return adjacencyList;
}

答案 1 :(得分:0)

我选择的最后一个答案是涉及的工作量最少,并允许我回收上面发布的原始2d数组代码,只是构建一个临时的2d数组并将所有引用存储在其中 - 创建所有邻接根据需要然后处理(简单地通过丢失范围)2d阵列。

这是使用2d阵列系统的实际方法。嵌套for循环后面的第一对语句就是:

private void ConstructAdjacencyList() {
    Tile[,] tempArray = new Tile[mapWidth, mapHeight];

    int count = 0;

    // Populate the temp 2D array with list references
    for (int x = 0; x < mapWidth; x++) {
        for (int y = 0; y < mapHeight; y++) {
            tempArray[x,y] = islandMap[count];
            count++;            
        }
    }

    // Create Adjacency List using our TempArray
    for (int x = 0; x < mapWidth; x++) {
        for (int y = 0; y < mapHeight; y++) {
            // Bool to find position of point
            bool omitLeft = false;      bool omitRight = false;
            bool omitTop = false;       bool omitBottom = false;
            // Enable bools based on position, reset on each loop               
            if (x == 0)
                omitLeft = true;                
            else if (x == mapWidth - 1) // Optimize with if else to split checks in half.
                omitRight = true;               
            if (y == 0)
                omitTop = true;             
            else if (y == mapHeight - 1)
                omitBottom = true;

            // Add entries to list based on bool settings
            if (!omitLeft) {
                // Left center
                tempArray[x,y].adjacent.Add(tempArray[x-1,y]);
                if (!omitTop)
                    tempArray[x,y].adjacent.Add(tempArray[x-1,y-1]);
                if (!omitBottom)
                    tempArray[x,y].adjacent.Add(tempArray[x-1,y+1]);
            }

            if (!omitTop) // Top Center
                tempArray[x,y].adjacent.Add(tempArray[x,y-1]);
            if (!omitBottom) // Bottom Center
                tempArray[x,y].adjacent.Add(tempArray[x,y+1]);

            if (!omitRight) {
                // Right Center
                tempArray[x,y].adjacent.Add(tempArray[x+1,y]);
                if (!omitTop)
                    tempArray[x,y].adjacent.Add(tempArray[x+1,y-1]);
                if (!omitBottom)
                    tempArray[x,y].adjacent.Add(tempArray[x+1,y+1]);
            }               
        }
    } // End Adjacency

    Debug.Log ("Adjacencies Built");
}

为了确保按照我想要的方式解决这个问题,我通过设置一个随机立方体并在该区域周围测试了各个点以确保没有错误而没有错误来进行视觉测试。

最终结果符合预期,如下所示:

Element Selection

感谢您的帮助:)