使用生物群系生成2D瓦片地图

时间:2014-03-28 13:03:51

标签: c++ algorithm map 2d generator

我想用生物群系生成一个二维瓷砖地图(比方说:沙漠,草地,雪地)。 我有一些算法的想法,比如放几个随机的瓷砖然后尝试扩展,但我完全不知道如何确定何时扩展以及何时不扩展。 (我所做的尝试总是以无限递归结束)

我正在寻找的结果是这样的:(生物群落较少)

有一种简单的方法吗?

2 个答案:

答案 0 :(得分:3)

我用一个简单的算法测试了你的问题:

  1. 在您的字段上随机设置具有生物群系类型的点
  2. 遍历整个字段并将生物群系类型设置为最近的点
  3. 示例结果(X标记步骤1中的生物群落点):

    % % % % % % % % % % % % % % % % % % I I I I I I I I I I I I I I 
    % % % % % % % % % % % % % % % % % I I I I I I I I I I I I I I I 
    % % % % % % % % % % % % % % % % I I I I I I I I I I I I I I I I 
    % % % % % % % % % % % % % % % % I I I I I I I I I I I I I I I I 
    % % % % % % % % % % % % % % % I I I I I I I I I I I I I I I I I 
    % % % % % X % % % % % % % % I I I I I I I I I I I I I I I I I I 
    % % % % % % % % % % % % % % I I I I I I I I I I I I I I I I I I 
    % % % % % % % % % % % % % I I I I I I I I I I I I I I I I I I I 
    O O O O O O O O O O O O O I I I I I I I I I I I I I I I I I I I 
    O O O O O O O O O O O O O I I I I I I I I I I I I I I I I I I I 
    O O O O O X O O O O O O I I I I I I I I I I I I I I I I I I I I 
    O O O O O O O O O O O O I I I I I I I I I I I I I I I I I I I I 
    O O O O O O O O O O O O I I I I I I I I I I I I I I I I I I I I 
    O O O O O O O O O O O O I I I I I I X I I I I I I I I I I I I I 
    O O O O O O O O O O O I I I I I I I I I I I I I I I I I I I I + 
    O O O O O O O O O O O I I I I I I I I I I I I I I I I I I I + + 
    O O O O O O O O O O O I I I I I I I I I I I I I I I I I + + + + 
    O O O O O O O O O O O I I I I I I I I I I I I I I I I + + + + + 
    O O O O O O O O O O O I I I I I I I I I I I I I I + + + + + + + 
    O O O O O O O O O O I I I I I I I I I I I I I + + + + + + + + + 
    O O O O O O O O O O I I I I I I I I I I I I + + + + + + + + + + 
    O O O O O O O O O O I I I I I I I I I I + + + + + + + + + + + + 
    O O O O O O O O O O I I I I I I I I + + + + + + + + + + + + + + 
    O O O O O O O O O I I I I I I I I + + + + + + + + + + + + + + + 
    O O O O O O O O O I I I I I I + + + + + + + + + + + + + + + + + 
    O O O O O O O O O I I I I I + + + + + + + + + + + + + + + + + + 
    O O O O O O O O O I I I + + + + + + + + + + + + + + X + + + + + 
    O O O O O O O O I I + + + + + + + + + + + + + + + + + + + + + + 
    O O O O O O O O I + + + + + + + + + + + + + + + + + + + + + + + 
    O O O O O O O O + + + + + + + + + + + + + + + + + + + + + + + + 
    O O O O O O O + + + + + + + + + + + + + + + + + + + + + + + + + 
    O O O O O O + + + + + + + + + + + + + + + + + + + + + + + + + + 
    

    我使用Java作为解决方案但不应该很难将其转换为C / C ++

    // a simple 'struct' to hold some vars
    class BiomeInfo {
        char type;
        int x;
        int y;
    }
    
    接下来我们设置一些要点。您可以随机添加此任务,也可以多次添加任何类型

        char[][] field = new field[32][32];
    
        biomeInfo[0].type = '#';
        biomeInfo[0].x = 5;
        biomeInfo[0].y = 5;
    
        biomeInfo[1].type = 'O';
        biomeInfo[1].x = 10;
        biomeInfo[1].y = 5;
    
        biomeInfo[2].type = 'I';
        biomeInfo[2].x = 13;
        biomeInfo[2].y = 18;
    
        biomeInfo[3].type = '+';
        biomeInfo[3].x = 26;
        biomeInfo[3].y = 26;
    

    下一步:走过田野

        for (int i = 0; i < field.length; i++) {
            for (int j = 0; j < field[0].length; j++) {
                char nearest = '.'; // value here doesn't matter
                int dist = Integer.MAX_VALUE; // select a big number
    
                // walk over each biomeInfo
                for (int z = 0; z < biomeInfo.length; z++) {
    
                    // calculate the difference in x and y direction
                    int xdiff = biomeInfo[z].x - i;
                    int ydiff = biomeInfo[z].y - j;
    
                    // calculate euclidean distance, sqrt is not needed
                    // because we only compare and do not need the real value
                    int cdist = xdiff*xdiff + ydiff*ydiff;
    
                    // is the current distance smaller than the old distance?
                    // if yes, take this biome
                    if (cdist < dist) {
                        nearest = biomeInfo[z].type;
                        dist = cdist;
                    }
                }
    
                // set the field to the nearest biome       
                field[i][j] = nearest;
    
                // you can mark the biome point with this code
                // if (dist == 0) {
                //    field[i][j] = 'X';
                // }
            }
        }
    

    最后打印字段:

        for (int i = 0; i < field.length; i++) {
            for (int j = 0; j < field[0].length; j++) {
                System.out.printf("%c ", field[i][j]);
            }
            System.out.printf("%n"); // %n means newline
        }
        System.out.printf("%n");
    

答案 1 :(得分:1)

图片上的行名称为Voronoi diagram。维基百科页面mentions一些用于查找该算法的算法,或双重Delaunay triangulation。一个简单的方法如下:对于每个控制点,在该点和每个其他控制点之间绘制中间线,按照与Ox轴的角度对这些线进行排序,然后按顺序遍历它们以在控制点周围构造多边形

完成后,将类型分配给切片应该很容易。您只需查看切片的中心并找到它所属图表的哪个面。如果您需要更高的精度,对于每个图块,您可以计算每个面的交叉区域,并选择面积最大的区域。